├── boot ├── arch │ ├── mips64 │ │ └── loongson3a │ │ │ ├── boot.markdown │ │ │ ├── bootsect.ld │ │ │ └── bootsect.c │ └── armv7a-le │ │ └── zynq7000 │ │ ├── mbr.ld │ │ ├── vector.S │ │ └── bootmain.c └── Makefile.mips64 ├── kern ├── init │ ├── stub.c │ └── main.c ├── sched │ └── DESIGN ├── mm │ └── DESIGN ├── arch │ └── mips64 │ │ ├── ldscript.ld │ │ ├── start.S │ │ ├── include │ │ └── asm │ │ │ ├── regdef.h │ │ │ ├── asm.h │ │ │ └── cp0regdef.h │ │ ├── trap │ │ ├── traps.c │ │ └── except.S │ │ └── setup.c ├── debug │ ├── debug_info_test.c │ └── debug_info.c └── FILES ├── firmware ├── arch │ └── armv7a-le │ │ ├── zynq7000 │ │ ├── zedboard │ │ │ └── board.m4 │ │ └── chip.m4 │ │ ├── bootasm.S │ │ ├── vector.S │ │ ├── firmware.m4 │ │ └── bootmain.c └── FILES ├── user └── FILES ├── doc ├── coding-style.markdown ├── README.md ├── challenges │ └── highmem.markdown ├── booting.markdown └── labs │ ├── lab0-prerequisites.markdown │ └── lab1-booting.markdown ├── Makefile ├── drivers ├── ata │ ├── ata_cmd.h │ ├── ahci_cmd.h │ ├── ahci.h │ ├── ahci.c │ └── ahci_fis.h ├── clock │ ├── rtc.h │ ├── gtc-a9mpcore.c │ ├── mc146818.c │ ├── gtc-a9mpcore.h │ └── mc146818.h ├── serial │ ├── uart.c │ ├── uart.h │ ├── uart-printf.c │ ├── uart16550.c │ ├── uart-zynq7000.c │ ├── uart-zynq7000.h │ └── uart16550.h ├── FILES ├── misc │ ├── division-arm.c │ ├── dtb-zynq7000.c │ └── dtb-zynq7000.h └── sd │ └── sd-zynq7000.h ├── include ├── string.h ├── arch │ ├── mips64 │ │ └── asm │ │ │ ├── util.h │ │ │ ├── setup.h │ │ │ ├── mach-loongson3a │ │ │ └── mach │ │ │ │ ├── pci.h │ │ │ │ └── config.h │ │ │ ├── smp.h │ │ │ ├── mm │ │ │ └── page.h │ │ │ ├── config.h │ │ │ ├── pci.h │ │ │ ├── irq.h │ │ │ ├── io.h │ │ │ ├── regdef.h │ │ │ ├── addrspace.h │ │ │ ├── asm.h │ │ │ └── cp0regdef.h │ └── armv7a-le │ │ └── asm │ │ ├── mach-zynq7000 │ │ └── config.h │ │ ├── config.h │ │ ├── io.h │ │ └── irq.h ├── pdebug.h ├── stdarg.h ├── debug.h ├── stdio.h ├── sleep.h ├── config.h ├── printk.h ├── smp.h ├── stddef.h ├── sys │ └── types.h ├── device.h ├── stab.h └── errno.h ├── tools └── stab │ ├── Makefile │ └── readstab.c ├── lib ├── FILES └── libc │ ├── string │ ├── memset.c │ └── memcpy.c │ └── stdio │ └── snprintf.c ├── FILES ├── Makefile.armv7a-le ├── README.md └── Makefile.mips64 /boot/arch/mips64/loongson3a/boot.markdown: -------------------------------------------------------------------------------- 1 | # Booting 2 | 3 | (TODO: describe how the kernel should be put in storage in order to properly 4 | boot) 5 | -------------------------------------------------------------------------------- /kern/init/stub.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | void main(void) 5 | { 6 | uart_spin_printf("Hello from kernel!\r\n"); 7 | 8 | for (;;) 9 | /* nothing */; 10 | } 11 | -------------------------------------------------------------------------------- /kern/sched/DESIGN: -------------------------------------------------------------------------------- 1 | [BarclayII] 2 | I used a list rather than a PID-indexed array to hold the processes. 3 | 4 | The scheduler I chose is the old O(1) scheduler, which is relatively easy to 5 | implement? 6 | -------------------------------------------------------------------------------- /firmware/arch/armv7a-le/zynq7000/zedboard/board.m4: -------------------------------------------------------------------------------- 1 | /* BOARD-SPECIFIC BEGIN */ 2 | 3 | /* Total ONBOARD memory */ 4 | define([ram_size], [512M]) 5 | [/* ram_size =] ram_size [*/] 6 | 7 | /* BOARD-SPECIFIC END */ 8 | 9 | -------------------------------------------------------------------------------- /user/FILES: -------------------------------------------------------------------------------- 1 | More suggestions are welcome. 2 | 3 | user: 4 | Userspace programs should be here. 5 | Each program should take one sub-directory. 6 | 7 | user/init: 8 | init(1) is preferred to be run in userspace. 9 | 10 | -------------------------------------------------------------------------------- /boot/arch/mips64/loongson3a/bootsect.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-tradlittlemips") 2 | OUTPUT_ARCH(mips) 3 | ENTRY(_boot) 4 | 5 | SECTIONS 6 | { 7 | . = 0x80100000; 8 | 9 | .text : { 10 | *(.text) 11 | } 12 | 13 | .data : { 14 | *(.data) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /firmware/arch/armv7a-le/zynq7000/chip.m4: -------------------------------------------------------------------------------- 1 | /* CHIP-SPECIFIC BEGIN */ 2 | 3 | /* size of address section to be filtered by SCU */ 4 | /* We are in NO-SCU state now, but RAM is ready. */ 5 | define([scu_sect_size], [1M]) 6 | [/* scu_sect_size =] scu_sect_size [*/] 7 | 8 | /* CHIP-SPECIFIC END */ 9 | -------------------------------------------------------------------------------- /boot/arch/armv7a-le/zynq7000/mbr.ld: -------------------------------------------------------------------------------- 1 | ENTRY(mbr_bootmain) 2 | 3 | MEMORY 4 | { 5 | MBR (rwx) : 6 | ORIGIN = 1M, 7 | LENGTH = 512 8 | } 9 | 10 | SECTIONS 11 | { 12 | .text : { 13 | *(.text .rodata) 14 | } 15 | .data : { 16 | *(.data) 17 | } 18 | .bss : { 19 | *(.bss) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /doc/coding-style.markdown: -------------------------------------------------------------------------------- 1 | # Coding style 2 | 3 | The coding style we use is mainly [BSD KNF Format](https://www.freebsd.org/cgi/man.cgi?query=style&sektion=9). It resembles K&R and deals line wrapping quite 4 | well. 5 | 6 | [Linux kernel coding style](https://www.kernel.org/doc/Documentation/CodingStyle) also have some good points albeit the strong language. 7 | 8 | TODO: add details 9 | -------------------------------------------------------------------------------- /kern/mm/DESIGN: -------------------------------------------------------------------------------- 1 | [BarclayII] 2 | I enabled incontiguous physical page allocation to solve fragmentation 3 | problems. An alloc_pages() call may return a list of pages which may 4 | be incontiguous (for example, returning a list with PFN 1, 3, 5, 6, 7). 5 | Not sure whether it's a good design... 6 | 7 | For virtual memory allocators I implemented a simple SLAB allocator 8 | (currently in xv6-Loongson3a). 9 | 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015 Gan Quan 2 | # 3 | # This program is free software; you can redistribute it and/or modify it 4 | # under the terms of the GNU General Public License as published by the 5 | # Free Software Foundation; either version 2 of the License, or (at your 6 | # option) any later version. 7 | 8 | # Read the ARCH variable passed in the command line, find the corresponding 9 | # architecture-specific Makefile, and load it. 10 | include Makefile.$(ARCH) 11 | -------------------------------------------------------------------------------- /drivers/ata/ata_cmd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _DRIVERS_ATA_ATA_CMD_H 12 | #define _DRIVERS_ATA_ATA_CMD_H 13 | 14 | #define ATA_IDENTIFY_DEVICE 0xec 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /boot/arch/armv7a-le/zynq7000/vector.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | .globl vector 12 | 13 | .text 14 | .arm 15 | 16 | vector: 17 | b uart_init 18 | b uart_enable 19 | b uart_spin_puts 20 | -------------------------------------------------------------------------------- /include/string.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _STRING_H 12 | #define _STRING_H 13 | 14 | #include 15 | 16 | void *memset(void *dst, int c, size_t n); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_UTIL_H 12 | #define _ASM_UTIL_H 13 | 14 | /* Align to 4 bytes */ 15 | #define FIX_INSTRUCTION_ADDR(x) (((x) | 3) ^ 3) 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /firmware/arch/armv7a-le/bootasm.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | .globl firmware_bootasm 12 | 13 | .text 14 | .arm 15 | 16 | firmware_bootasm: 17 | ldr sp, =firmware_vector 18 | movs fp, sp 19 | bl firmware_bootmain 20 | 21 | -------------------------------------------------------------------------------- /firmware/arch/armv7a-le/vector.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | .globl firmware_vector 12 | 13 | .text 14 | .arm 15 | 16 | firmware_vector: 17 | b firmware_bootasm 18 | b uart_init 19 | b uart_enable 20 | b uart_spin_puts 21 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/setup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_SETUP_H 12 | #define _ASM_SETUP_H 13 | 14 | /* CPU pipeline frequency */ 15 | extern unsigned long cpu_freq; 16 | 17 | void setup_arch(void); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/mach-loongson3a/mach/pci.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _MACH_PCI_H 12 | #define _MACH_PCI_H 13 | 14 | #define PCI_PORT_BASE 0x18000000 15 | 16 | #define pcimap(port) (PCI_PORT_BASE + (port)) 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /drivers/clock/rtc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _DRIVERS_CLOCK_RTC_H 12 | #define _DRIVERS_CLOCK_RTC_H 13 | 14 | #include 15 | 16 | #ifdef RTC_MC146818 17 | #include 18 | #endif /* RTC_MC146818 */ 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/arch/armv7a-le/asm/mach-zynq7000/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_MACH_CONFIG_H 12 | #define _ASM_MACH_CONFIG_H 13 | 14 | #include 15 | 16 | #define UART_ZYNQ7000 17 | #define SD_ZYNQ7000 18 | #define GTC_A9MPCORE 19 | 20 | #endif 21 | 22 | -------------------------------------------------------------------------------- /drivers/serial/uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | void uart_spin_puts(const char *str) 17 | { 18 | for (; *str != '\0'; ++str) 19 | uart_spin_putbyte((unsigned char)*str); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /include/pdebug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _PDEBUG_H 12 | #define _PDEBUG_H 13 | 14 | #include 15 | 16 | #ifdef DEBUG 17 | #include 18 | #define pdebug(...) uart_spin_printf(__VA_ARGS__) 19 | #else /* !DEBUG */ 20 | #define pdebug(...) 21 | #endif /* DEBUG */ 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/stdarg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _STDARG_H 12 | #define _STDARG_H 13 | 14 | typedef __builtin_va_list va_list; 15 | 16 | #define va_start(ap, last) (__builtin_va_start(ap, last)) 17 | #define va_arg(ap, type) (__builtin_va_arg(ap, type)) 18 | #define va_end(ap) (__builtin_va_end(ap)) 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/arch/armv7a-le/asm/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_CONFIG_H 12 | #define _ASM_CONFIG_H 13 | 14 | /* 15 | * Include machine-specific configurations. 16 | */ 17 | #ifdef MACH_ZYNQ7000 18 | #include 19 | #endif /* MACH_ZYNQ7000 */ 20 | 21 | #endif /* _ASM_CONFIG_H */ 22 | 23 | -------------------------------------------------------------------------------- /firmware/FILES: -------------------------------------------------------------------------------- 1 | More suggestions are welcome. 2 | 3 | bios: 4 | This is the place for holding all pre-bootloader sources. 5 | A separate Makefile target is expected for building them. 6 | 7 | bios/arch/$(ARCH): 8 | For architecture-dependent stuff, including arm, mips64, i386 (if any). 9 | 10 | bios/arch/$(ARCH)/$(MACH): 11 | Machine-dependent sources should go there. 12 | 13 | bios/include: 14 | For pre-bootloader architecture-independent headers. 15 | 16 | bios/arch/$(ARCH)/include/asm: 17 | Pre-bootloader architecture-dependent machine-independent headers should 18 | go there. 19 | 20 | bios/arch/$(ARCH)/include/asm/mach-$(MACH): 21 | Machine-dependent headers should go there. 22 | 23 | -------------------------------------------------------------------------------- /tools/stab/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015 Gan Quan 2 | # 3 | # This program is free software; you can redistribute it and/or modify it 4 | # under the terms of the GNU General Public License as published by the 5 | # Free Software Foundation; either version 2 of the License, or (at your 6 | # option) any later version. 7 | 8 | # readstab runs on host, so one really shouldn't use the cross-compiling 9 | # gcc. 10 | CC = gcc 11 | CFLAGS = -I../.. 12 | 13 | BINARY = readstab 14 | 15 | SRCS = readstab.c 16 | 17 | all: $(BINARY) 18 | 19 | $(BINARY): $(SRCS) 20 | $(CC) $(CFLAGS) -o $(BINARY) $(SRCS) 21 | 22 | clean: 23 | rm -f $(BINARY) 24 | 25 | .PHONY: all clean 26 | -------------------------------------------------------------------------------- /include/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _DEBUG_H 12 | #define _DEBUG_H 13 | 14 | #include 15 | 16 | struct debug_info { 17 | char *source_file; 18 | char *func_name; 19 | unsigned int func_addr_lo; 20 | unsigned int line_num; 21 | }; 22 | 23 | int get_debug_info(uintptr_t addr, struct debug_info *info, struct stab **last); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | ## Documentations 2 | 3 | Documentations inside the `doc` directory accept documents in these formats: 4 | 5 | 1. Text files (usually `*.txt`). 6 | 2. GitHub-flavored Markdown files (`*.md`). They are basically enhanced text 7 | files and are readable both under text viewers and GitHub. 8 | 3. PDFs. Documentations written in TeX are highly recommended to be compiled 9 | to PDFs. 10 | 11 | For lab users, move on to `labs/lab0-prerequisites.markdown` for introduction. 12 | 13 | For challengers, there's a `challenge` folder listing all challenges we could 14 | think of. These challenges are about techniques, algorithms and ideas used 15 | in real world. 16 | 17 | (TODO: add documentation folder descriptions) 18 | -------------------------------------------------------------------------------- /include/stdio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _STDIO_H 12 | #define _STDIO_H 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | int printf(const char *fmt, ...); 19 | int vprintf(const char *fmt, va_list ap); 20 | int snprintf(char *str, size_t size, const char *fmt, ...); 21 | int vsnprintf(char *str, size_t size, const char *fmt, va_list ap); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/sleep.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _SLEEP_H 12 | #define _SLEEP_H 13 | 14 | /* 15 | * These functions should be provided by some clock or timer. 16 | * But their usage should have no difference. 17 | * We simply define them here. You'll get a link-time error if 18 | * you use one but don't have one. 19 | */ 20 | void sleep(int sec); 21 | void usleep(int usec); 22 | 23 | #endif /* _SLEEP_H */ 24 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/smp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_SMP_H 12 | #define _ASM_SMP_H 13 | 14 | #ifndef __ASSEMBLER__ 15 | 16 | #include 17 | 18 | #ifndef cpuid 19 | 20 | inline unsigned int __cpuid(void) 21 | { 22 | return read_c0_ebase() & EBASE_CPUNUM_MASK; 23 | } 24 | 25 | #define cpuid() __cpuid() 26 | #endif /* !defined(cpuid) */ 27 | 28 | #endif /* !__ASSEMBLER__ */ 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _CONFIG_H 12 | #define _CONFIG_H 13 | 14 | /* 15 | * Include asm/config.h to include preset machine specific configurations, 16 | * which should be available on the manuals or documentations of those 17 | * machines. 18 | */ 19 | #include 20 | 21 | /* Other global configuration macros goes below. */ 22 | #define DEBUG /* enable pdebug() output */ 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /boot/arch/armv7a-le/zynq7000/bootmain.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | 13 | #define PRELOAD_VECTOR_BASE 0x1ff00000 14 | 15 | void (*uart_init)(void) = (void *)(PRELOAD_VECTOR_BASE + 0x4); 16 | void (*uart_enable)(void) = (void *)(PRELOAD_VECTOR_BASE + 0x8); 17 | void (*uart_spin_puts)(const char *) = (void *)(PRELOAD_VECTOR_BASE + 0xC); 18 | 19 | void mbr_bootmain(void) 20 | { 21 | uart_spin_puts("Hello, AIMv6!\r\n"); 22 | while(1); 23 | } 24 | 25 | -------------------------------------------------------------------------------- /lib/FILES: -------------------------------------------------------------------------------- 1 | More suggestions are welcome. 2 | 3 | lib: 4 | Generic libraries and C runtime sources should be here. 5 | 6 | lib/libc: 7 | C Library and C runtime routines should go there. 8 | 9 | lib/libc/arch: 10 | Architecture-dependent stuff of C Runtime. Mainly crt0.S and system call 11 | wrappers. 12 | 13 | ARM-specific notes: 14 | As of GCC 5.1 the C compiler will emit a call to __aeabi_idivmod or something 15 | alike to do division on software since ARM does not include hardware division. 16 | The corresponding functions should be inside lib/libc/arch/arm. 17 | 18 | One can see how GCC mess with division or modulo by printing out the assembly: 19 | 20 | gcc -S -o test.o test.c 21 | 22 | lib/libc/stdio: 23 | lib/libc/stdlib: 24 | lib/libc/string: 25 | ... 26 | C standard functions (sprintf(3), memset(3) etc.) should go there. 27 | -------------------------------------------------------------------------------- /include/printk.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _PRINTK_H 12 | #define _PRINTK_H 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | static inline ssize_t vprintk(const char *fmt, va_list ap) 19 | { 20 | return uart_spin_vprintf(fmt, ap); 21 | } 22 | 23 | static inline ssize_t printk(const char *fmt, ...) 24 | { 25 | ssize_t result; 26 | va_list ap; 27 | va_start(ap, fmt); 28 | result = vprintk(fmt, ap); 29 | va_end(ap); 30 | return result; 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /drivers/serial/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _DRIVERS_SERIAL_UART_H 12 | #define _DRIVERS_SERIAL_UART_H 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #ifdef UART16550 19 | #include 20 | #elif defined UART_ZYNQ7000 21 | #include 22 | #endif 23 | 24 | void uart_spin_puts(const char *str); 25 | ssize_t uart_spin_printf(const char *fmt, ...); 26 | ssize_t uart_spin_vprintf(const char *fmt, va_list ap); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /kern/arch/mips64/ldscript.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf64-tradlittlemips") 2 | OUTPUT_ARCH(mips) 3 | ENTRY(_start) 4 | 5 | SECTIONS 6 | { 7 | . = 0xffffffff80300000; 8 | 9 | .text : { 10 | *(.text) 11 | *(.rodata) 12 | } 13 | 14 | PROVIDE(__etext__ = . ); 15 | 16 | .reginfo : { *(.reginfo) } 17 | 18 | . = ALIGN(0x1000); 19 | 20 | .stabs : { 21 | PROVIDE(__STAB_BEGIN__ = .); 22 | *(.stab); 23 | PROVIDE(__STAB_END__ = .); 24 | BYTE(0) 25 | } 26 | 27 | .stabstr : { 28 | PROVIDE(__STABSTR_BEGIN__ = .); 29 | *(.stabstr); 30 | PROVIDE(__STABSTR_END__ = .); 31 | BYTE(0) 32 | } 33 | 34 | . = ALIGN(0x1000); 35 | 36 | PROVIDE(__data__ = . ); 37 | 38 | .data : { 39 | *(.data) 40 | } 41 | 42 | PROVIDE(__edata__ = . ); 43 | 44 | .bss : { 45 | *(.dynbss) 46 | *(.bss) 47 | } 48 | 49 | PROVIDE(__end__ = . ); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/mm/page.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_MM_PAGE_H 12 | #define _ASM_MM_PAGE_H 13 | 14 | #include 15 | #include 16 | 17 | static inline void *p2kv(unsigned long paddr) 18 | { 19 | return (paddr < MAXLOWERPHY) ? (void *)(paddr + KSEG0) : NULL; 20 | } 21 | 22 | static inline unsigned long kv2p(const void *kvaddr) 23 | { 24 | return ((unsigned long)kvaddr <= KSEG0_END && 25 | (unsigned long)kvaddr >= KSEG0_BASE) ? 26 | (unsigned long)kvaddr - KSEG0 : 0; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /kern/arch/mips64/start.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | LEAF(_start) 17 | /* TODO: assembly startup code */ 18 | mfc0 t0, CP0_STATUS 19 | or t0, ST_KX|ST_CU0|ST_IM 20 | or t0, ST_EXCM 21 | xor t0, ST_EXCM 22 | mtc0 t0, CP0_STATUS 23 | 24 | mtc0 zero, CP0_WATCHLO 25 | mtc0 zero, CP0_WATCHHI 26 | 27 | LA sp, cpu_info_stack 28 | ADDIU sp, KSTACKSIZE 29 | ADDIU sp, -32 30 | 31 | j main 32 | 33 | 1: j 1b 34 | nop 35 | END(_start) 36 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_CONFIG_H 12 | #define _ASM_CONFIG_H 13 | 14 | /* 15 | * Machine selection goes here. 16 | * 17 | * Usually machine should be selected by specifying parameters in make, which 18 | * adds macro definitions through CFLAGS, rather than directly modifying the 19 | * code here. 20 | */ 21 | 22 | /* #define MACH_LOONGSON2H */ /* Loongson 2H */ 23 | 24 | /* 25 | * Include machine-specific configurations. 26 | */ 27 | #include 28 | 29 | /* Other architecture configuration macros goes below. */ 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /drivers/serial/uart-printf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | ssize_t uart_spin_printf(const char *fmt, ...) 17 | { 18 | int result; 19 | va_list ap; 20 | va_start(ap, fmt); 21 | result = uart_spin_vprintf(fmt, ap); 22 | va_end(ap); 23 | return result; 24 | } 25 | 26 | ssize_t uart_spin_vprintf(const char *fmt, va_list ap) 27 | { 28 | int result; 29 | char printf_buf[BUFSIZ]; 30 | result = vsnprintf(printf_buf, BUFSIZ, fmt, ap); 31 | uart_spin_puts(printf_buf); 32 | return result; 33 | } 34 | -------------------------------------------------------------------------------- /firmware/arch/armv7a-le/firmware.m4: -------------------------------------------------------------------------------- 1 | changecom(`/*', `*/') 2 | changequote([,]) 3 | /* 4 | * Copyright (C) 2015 David Gao 5 | * 6 | * This program is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; either version 2 of the License, or (at your 9 | * option) any later version. 10 | * 11 | */ 12 | 13 | sinclude([board.m4]) 14 | sinclude([chip.m4]) 15 | 16 | define([preload_size], [1M]) 17 | [/* preload_size =] preload_size [*/] 18 | 19 | MEMORY 20 | { 21 | FIRMWARE (rwx) : 22 | ORIGIN = ram_size - preload_size, 23 | LENGTH = preload_size 24 | } 25 | 26 | SECTIONS 27 | { 28 | .vector : { 29 | *vector.o(.text) 30 | } 31 | .text : { 32 | *(.text) 33 | } 34 | .rodata : { 35 | *(.rodata) 36 | } 37 | .data : { 38 | *(.data) 39 | } 40 | .bss : { 41 | *(.bss) 42 | } 43 | } 44 | 45 | ENTRY(firmware_vector) 46 | -------------------------------------------------------------------------------- /drivers/FILES: -------------------------------------------------------------------------------- 1 | More suggestions are welcome. 2 | I didn't think thoroughly of how to separate between early immediate accesses 3 | (like loading file from disk during booting) and late device configurations 4 | (like initializing devfs). Besides, xv6 on i386 seems to interact with UART 5 | via inb() and outb(), so I'm not sure whether we should wrap memory-mapped 6 | hardware register accesses into functions to maintain compatibility. 7 | The following is only a possible organization. 8 | 9 | drivers: 10 | For driver-specific stuff. 11 | 12 | The following drivers probably should be prioritized: 13 | 1. UART driver 14 | 2. AHCI driver (for controlling SATA) 15 | 3. SD driver (?) (for Zedboard) 16 | 17 | drivers/ata: 18 | ATA (including SATA) driver source codes. 19 | 20 | drivers/include: 21 | Headers for drivers. 22 | 23 | drivers/sd: 24 | Driver source codes for SD cards (?) 25 | 26 | drivers/serial: 27 | Driver source codes for serial console, e.g. UART. 28 | 29 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/mach-loongson3a/mach/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _MACH_CONFIG_H 12 | #define _MACH_CONFIG_H 13 | 14 | /* 15 | * Loongson 3A specific configurations. 16 | * 17 | * The hardware register addresses are preset by the manufacturer. 18 | */ 19 | 20 | #define UART16550 21 | 22 | #define UART0_BASE 0x1fe001e0 23 | 24 | #define UART_BASE UART0_BASE 25 | 26 | #define RTC_MC146818 27 | 28 | /* Loongson 3A increases COUNT register by one every 2 cycles */ 29 | #define COUNT_TO_FREQ(count) ((count) * 2) 30 | #define FREQ_TO_COUNT(freq) ((freq) / 2) 31 | 32 | #define NR_CPUS 4 /* 4 cores */ 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/smp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _SMP_H 12 | #define _SMP_H 13 | 14 | #include 15 | #include 16 | 17 | #define KSTACKSIZE 8192 18 | 19 | #ifndef __ASSEMBLER__ 20 | 21 | /* per-CPU info */ 22 | struct cpuinfo { 23 | unsigned int cpuno; /* CPU # */ 24 | unsigned int ticks; /* # of ticks - for clock interrupt */ 25 | }; 26 | 27 | union cpu_info_stack { 28 | struct cpuinfo cpuinfo; 29 | unsigned char stack[KSTACKSIZE]; 30 | }; 31 | 32 | extern union cpu_info_stack cpu_info_stack[]; 33 | 34 | #define current_cpuinfo (cpu_info_stack[cpuid()].cpuinfo) 35 | 36 | #endif /* !__ASSEMBLER__ */ 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/pci.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_PCI_H 12 | #define _ASM_PCI_H 13 | 14 | #include 15 | #include 16 | 17 | /* 18 | * inb, inw, ind are equivalents for inb, inw, ind instructions on x86 19 | * for accessing PCI ports. 20 | * 21 | * MIPS PCI mapping is really machine-specific. 22 | */ 23 | #define inb(port) in8(pcimap(port)) 24 | #define outb(port, val) out8(pcimap(port), val) 25 | 26 | #define inw(port) in16(pcimap(port)) 27 | #define outw(port, val) out16(pcimap(port), val) 28 | 29 | #define ind(port) in32(pcimap(port)) 30 | #define outd(port, val) out32(pcimap(port), val) 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/irq.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_IRQ_H 12 | #define _ASM_IRQ_H 13 | 14 | #define local_irq_enable() asm volatile ("ei") 15 | 16 | #define local_irq_disable() asm volatile ("di") 17 | 18 | #define local_irq_save(flags) \ 19 | asm volatile ( \ 20 | "di %0;" \ 21 | "andi %0, 1;" \ 22 | : "=r"(flags) \ 23 | : /* no input */ \ 24 | : "memory" \ 25 | ) 26 | 27 | #define local_irq_restore(flags) \ 28 | asm volatile ( \ 29 | " beqz %0, 1f;" \ 30 | " di;" \ 31 | " ei;" \ 32 | "1:" \ 33 | : /* no output */ \ 34 | : "r"(flags) \ 35 | : "memory" \ 36 | ) 37 | 38 | void mach_init_irq(void); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /include/stddef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _STDDEF_H 12 | #define _STDDEF_H 13 | 14 | #ifndef NULL 15 | #define NULL (void *)0 16 | #endif 17 | 18 | #ifndef BUFSIZ 19 | #define BUFSIZ 1024 20 | #endif 21 | 22 | #define MEMBER_OFFSET(struct, member_name) \ 23 | ((unsigned long)&(((struct *)0)->member_name)) 24 | 25 | #define member_to_struct(addr, struct, member_name) \ 26 | ((struct *)((unsigned long)(addr) - MEMBER_OFFSET(struct, member_name))) 27 | 28 | /* 29 | * An extremely inaccurate busy-wait loop for delaying @t milliseconds 30 | */ 31 | static inline void delay(unsigned long t) 32 | { 33 | register unsigned long i; 34 | for (i = 0; i < t * 10000; ++i) 35 | asm (""); 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/io.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_IO_H 12 | #define _ASM_IO_H 13 | 14 | #include 15 | #include 16 | 17 | #define iomap(addr) (IO_BASE + (addr)) 18 | 19 | /* 20 | * in8() and out8() for MIPS receives physical address as parameter 21 | */ 22 | #define in8(addr) \ 23 | (*(volatile uchar *)iomap(addr)) 24 | #define out8(addr, data) \ 25 | ((*(volatile uchar *)iomap(addr)) = (data)) 26 | 27 | #define in16(addr) \ 28 | (*(volatile ushort *)iomap(addr)) 29 | #define out16(addr, data) \ 30 | ((*(volatile ushort *)iomap(addr)) = (data)) 31 | 32 | #define in32(addr) \ 33 | (*(volatile uint *)iomap(addr)) 34 | #define out32(addr, data) \ 35 | ((*(volatile uint *)iomap(addr)) = (data)) 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /drivers/misc/division-arm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | /* 12 | * Provide integer division and modulus as Cortex-A9 does not have its own. 13 | * These functions should not be called directly. 14 | */ 15 | 16 | unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator) 17 | { 18 | unsigned tmp = 1; 19 | unsigned shift = denominator << 1; 20 | unsigned quot = 0; 21 | /* TODO handle zero denominator */ 22 | while (shift <= numerator) { 23 | denominator <<= 1; 24 | shift <<= 1; 25 | tmp <<= 1; 26 | } 27 | while (tmp > 0) { 28 | if (numerator > denominator){ 29 | quot += tmp; 30 | numerator -= denominator; 31 | } 32 | denominator >>= 1; 33 | tmp >>= 1; 34 | } 35 | asm volatile ( 36 | "mov r1, %[rem]"::[rem] "r" (numerator) 37 | ); 38 | return quot; 39 | } 40 | -------------------------------------------------------------------------------- /kern/debug/debug_info_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | void call3(void) 17 | { 18 | struct debug_info info; 19 | struct stab *last = NULL; 20 | printk("Inside call3\r\n"); 21 | get_debug_info(call3, &info, &last); 22 | printk("%016x %s:%d %s (%08x)\r\n", 23 | call3, 24 | info.source_file, 25 | info.line_num, 26 | info.func_name, 27 | info.func_addr_lo 28 | ); 29 | } 30 | 31 | void call2(void) 32 | { 33 | printk("Inside call2\r\n"); 34 | call3(); 35 | } 36 | 37 | void call1(void) 38 | { 39 | printk("Inside call1\r\n"); 40 | call2(); 41 | } 42 | 43 | void test_stacktrace(void) 44 | { 45 | printk("********** Testing stacktrace **********\r\n"); 46 | call1(); 47 | } 48 | -------------------------------------------------------------------------------- /doc/challenges/highmem.markdown: -------------------------------------------------------------------------------- 1 | # High memory mechanism 2 | 3 | [*High memory*](https://en.wikipedia.org/wiki/HighMem) (or *HighMem* in short) 4 | is a workaround for kernel to access higher physical addresses. It is used by 5 | Linux for ensuring total control of the whole physical address space in case 6 | of: 7 | 8 | 1. The physical address space exceeds the virtual one in size. In real world 9 | this is addressed by Physical Address Extension (PAE) which is a somewhat 10 | similar idea. Of course, in real world, you're unlikely to have a 32-bit 11 | computer with a 8GB RAM. 12 | 2. Devices taking sooooo much physical address space that direct memory mapping 13 | is infeasible. `ioremap` in Linux which shares some aspects with HighMem deals 14 | with this situation. Again, it's very unlikely. 15 | 3. The operating system designer insists to do so. 16 | 17 | BSD seems to ignore HighMem altogether. Maybe they didn't care about these 18 | dire cases. 19 | 20 | We didn't implement HighMem in this project, and leave it to those who are 21 | interested and passionate as an additional 22 | exercise/challenge/bonus/surprise/trouble/whatever. 23 | 24 | ### Problem 25 | 26 | ### Solution 27 | 28 | ### Interfaces 29 | -------------------------------------------------------------------------------- /drivers/serial/uart16550.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | 13 | #ifdef UART16550 14 | 15 | #include 16 | #include 17 | 18 | void uart_init(void) 19 | { 20 | } 21 | 22 | void uart_enable(void) 23 | { 24 | register unsigned char mcr = UART_READ(UART_MODEM_CONTROL); 25 | UART_WRITE(UART_MODEM_CONTROL, mcr | UART_MCR_RTSC | UART_MCR_DTRC); 26 | } 27 | 28 | void uart_disable(void) 29 | { 30 | register unsigned char mcr = UART_READ(UART_MODEM_CONTROL); 31 | UART_WRITE(UART_MODEM_CONTROL, mcr & ~(UART_MCR_RTSC | UART_MCR_DTRC)); 32 | } 33 | 34 | unsigned char uart_spin_getbyte(void) 35 | { 36 | while (!(UART_READ(UART_LINE_STATUS) & UART_LSR_DATA_READY)) 37 | /* nothing */; 38 | return UART_READ(UART_RCV_BUFFER); 39 | } 40 | 41 | void uart_spin_putbyte(unsigned char byte) 42 | { 43 | while (!(UART_READ(UART_LINE_STATUS) & UART_LSR_THRE)) 44 | /* nothing */; 45 | UART_WRITE(UART_TRANS_HOLD, byte); 46 | } 47 | 48 | #endif /* UART16550 */ 49 | -------------------------------------------------------------------------------- /drivers/clock/gtc-a9mpcore.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | 13 | #ifdef GTC_A9MPCORE 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | u64 gtc_get_time() 21 | { 22 | u64 time; 23 | u32 hi, lo, tmp; 24 | /* HI-LO-HI reading because GTC is 64bit */ 25 | do { 26 | hi = in32(GTC_BASE + GTC_COUNTER_HI_OFFSET); 27 | lo = in32(GTC_BASE + GTC_COUNTER_LO_OFFSET); 28 | tmp = in32(GTC_BASE + GTC_COUNTER_HI_OFFSET); 29 | } while (hi != tmp); 30 | time = (u64)hi << 32; 31 | time |= lo; 32 | return time; 33 | } 34 | 35 | void sleep(int sec) 36 | { 37 | u64 time, time1; 38 | time = gtc_get_time(); 39 | time += GTC_TPS * sec; 40 | do { 41 | time1 = gtc_get_time(); 42 | } while (time1 < time); 43 | } 44 | 45 | void usleep(int usec) 46 | { 47 | u64 time, time1; 48 | time = gtc_get_time(); 49 | time += GTC_TPUS * usec; 50 | do { 51 | time1 = gtc_get_time(); 52 | } while (time1 < time); 53 | } 54 | 55 | #endif /* GTC_A9MPCORE */ 56 | -------------------------------------------------------------------------------- /include/arch/armv7a-le/asm/io.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_IO_H 12 | #define _ASM_IO_H 13 | 14 | /* 15 | * Basic IO for ARMv7A Little Endian machines. 16 | * IO should always operate on unsigned data. 17 | */ 18 | 19 | static inline unsigned char in8(unsigned long addr) 20 | { 21 | return *(volatile unsigned char *)addr; 22 | } 23 | 24 | static inline unsigned short in16(unsigned long addr) 25 | { 26 | return *(volatile unsigned short *)addr; 27 | } 28 | 29 | static inline unsigned long in32(unsigned long addr) 30 | { 31 | return *(volatile unsigned long *)addr; 32 | } 33 | 34 | 35 | static inline void out8(unsigned long addr, unsigned char data) 36 | { 37 | *(volatile unsigned char *)addr = data; 38 | } 39 | 40 | static inline void out16(unsigned long addr, unsigned short data) 41 | { 42 | *(volatile unsigned short *)addr = data; 43 | } 44 | 45 | static inline void out32(unsigned long addr, unsigned long data) 46 | { 47 | *(volatile unsigned long *)addr = data; 48 | } 49 | 50 | #endif /* _ASM_IO_H */ 51 | 52 | -------------------------------------------------------------------------------- /drivers/clock/mc146818.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | /* 12 | * MC146818 - Morotola Real Time Clock (RTC) + RAM 13 | * 14 | * References: 15 | * http://www.loongnix.cn/dev/ftp/doc/02data%20sheet/loongson3a/SB/43009_sb7xx_rrg_pub_1.00.pdf 16 | */ 17 | 18 | #include 19 | 20 | #ifdef RTC_MC146818 21 | 22 | #include 23 | 24 | void rtc_init(void) 25 | { 26 | /* 27 | * Set DV0 to enable access to century register, no interrupt, 28 | * and enable oscillator. 29 | */ 30 | rtc_writereg(DS_REG_CTLA, DS_CTLA_DV0 | DS_CTLA_DV1); 31 | /* 24hr mode */ 32 | rtc_writereg(DS_REG_CTLB, DS_CTLB_24); 33 | } 34 | 35 | unsigned char rtc_gettimereg(unsigned char r) 36 | { 37 | return bcd_to_byte(rtc_readreg(r)); 38 | } 39 | 40 | void rtc_settimereg(unsigned char r, unsigned char v) 41 | { 42 | unsigned char ctlb = rtc_readreg(DS_REG_CTLB); 43 | rtc_writereg(DS_REG_CTLB, ctlb | DS_CTLB_SET); 44 | rtc_writereg(r, byte_to_bcd(v)); 45 | rtc_writereg(DS_REG_CTLB, ctlb & ~DS_CTLB_SET); 46 | } 47 | 48 | #endif /* RTC_MC146818 */ 49 | -------------------------------------------------------------------------------- /kern/init/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | /* 17 | * TODO: add setup_arch() for hardware probing/detection/anything funny for 18 | * each architecture. The function should be declared in asm/setup.h. 19 | */ 20 | #include 21 | 22 | union cpu_info_stack cpu_info_stack[NR_CPUS]; 23 | 24 | int main(void) 25 | { 26 | /* 27 | * 0. Hardware probing etc. 28 | * 1. Trap 29 | * 2. SMP per-CPU setup 30 | * 3. Interrupt, including PIC, LAPIC, IOAPIC etc. 31 | * 4. Disk storage 32 | * 5. Memory mapping, including page tables, allocators etc. 33 | * a) Swapping 34 | * 6. Scheduler 35 | * 7. File system 36 | * 8. SMP Startup 37 | * a) Slave CPUs should skip to step 11 38 | * 9. Fork and load /sbin/init into process table 39 | * 10. Enable swapping & scheduler 40 | * 11. Enter idle stage 41 | */ 42 | printk("Hello from kernel!\r\n"); 43 | 44 | /* 0. */ 45 | setup_arch(); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/regdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is subject to the terms and conditions of the GNU General Public 3 | * License. See the file "COPYING" in the main directory of this archive 4 | * for more details. 5 | * 6 | * Copyright (C) 1994, 1995 by Ralf Baechle 7 | * Copyright (C) 2015 Gan Quan 8 | */ 9 | 10 | #ifndef __ASM_MIPS_REGDEF_H 11 | #define __ASM_MIPS_REGDEF_H 12 | 13 | /* 14 | * Symbolic register names for 32 bit ABI 15 | * 16 | * Although I'm programming on a 64-bit machine, I retain the 32 bit register 17 | * names. 18 | */ 19 | #define zero $0 /* wired zero */ 20 | #define AT $1 /* assembler temp - uppercase because of ".set at" */ 21 | #define v0 $2 /* return value */ 22 | #define v1 $3 23 | #define a0 $4 /* argument registers */ 24 | #define a1 $5 25 | #define a2 $6 26 | #define a3 $7 27 | #define t0 $8 28 | #define t1 $9 29 | #define t2 $10 30 | #define t3 $11 31 | #define t4 $12 /* caller saved */ 32 | #define t5 $13 33 | #define t6 $14 34 | #define t7 $15 35 | #define s0 $16 /* callee saved */ 36 | #define s1 $17 37 | #define s2 $18 38 | #define s3 $19 39 | #define s4 $20 40 | #define s5 $21 41 | #define s6 $22 42 | #define s7 $23 43 | #define t8 $24 44 | #define t9 $25 45 | #define jp $26 46 | #define k0 $26 47 | #define k1 $27 48 | #define gp $28 49 | #define sp $29 50 | #define fp $30 51 | #define s8 $30 52 | #define ra $31 53 | 54 | #endif /* __ASM_MIPS_REGDEF_H */ 55 | -------------------------------------------------------------------------------- /kern/arch/mips64/include/asm/regdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is subject to the terms and conditions of the GNU General Public 3 | * License. See the file "COPYING" in the main directory of this archive 4 | * for more details. 5 | * 6 | * Copyright (C) 1994, 1995 by Ralf Baechle 7 | * Copyright (C) 2015 Gan Quan 8 | */ 9 | 10 | #ifndef __ASM_MIPS_REGDEF_H 11 | #define __ASM_MIPS_REGDEF_H 12 | 13 | /* 14 | * Symbolic register names for 32 bit ABI 15 | * 16 | * Although I'm programming on a 64-bit machine, I retain the 32 bit register 17 | * names. 18 | */ 19 | #define zero $0 /* wired zero */ 20 | #define AT $1 /* assembler temp - uppercase because of ".set at" */ 21 | #define v0 $2 /* return value */ 22 | #define v1 $3 23 | #define a0 $4 /* argument registers */ 24 | #define a1 $5 25 | #define a2 $6 26 | #define a3 $7 27 | #define t0 $8 28 | #define t1 $9 29 | #define t2 $10 30 | #define t3 $11 31 | #define t4 $12 /* caller saved */ 32 | #define t5 $13 33 | #define t6 $14 34 | #define t7 $15 35 | #define s0 $16 /* callee saved */ 36 | #define s1 $17 37 | #define s2 $18 38 | #define s3 $19 39 | #define s4 $20 40 | #define s5 $21 41 | #define s6 $22 42 | #define s7 $23 43 | #define t8 $24 44 | #define t9 $25 45 | #define jp $26 46 | #define k0 $26 47 | #define k1 $27 48 | #define gp $28 49 | #define sp $29 50 | #define fp $30 51 | #define s8 $30 52 | #define ra $31 53 | 54 | #endif /* __ASM_MIPS_REGDEF_H */ 55 | -------------------------------------------------------------------------------- /FILES: -------------------------------------------------------------------------------- 1 | The source organization is inspired by the ones in Linux and OpenBSD. 2 | More suggestions are welcome. 3 | 4 | The sources are separated into: bootloader, drivers, kernel, C library, and 5 | userspace programs. 6 | 7 | ./: 8 | No separate files other than Makefile or autotools-related stuff (if any) 9 | should really be placed here, I guess? 10 | 11 | bios: 12 | Place everything prior to bootloader (e.g. BIOS, bootROM, etc.) there. 13 | 14 | boot: 15 | Place bootloader-related source codes and headers there. 16 | 17 | doc: 18 | Place documentations there, if any. 19 | 20 | drivers: 21 | Place driver-specific sources and headers there. 22 | Both bootloader and kernel may need to play with drivers. 23 | 24 | kern: 25 | Place all kernel-specific source codes and headers (including but not limited 26 | to: memory allocator, exception handler, scheduler) there. 27 | 28 | include: 29 | Place all generic C Library headers (e.g. stdio.h, stdlib.h, assert.h) there. 30 | Component-specific headers should be placed inside directories such as 31 | kern/include etc. 32 | General architecture-specific headers are placed inside include/arch/$ARCH/asm. 33 | 34 | lib: 35 | Place all generic C Library sources (e.g. sprintf(3), strlcpy(3), memset(3)), 36 | and C Runtime sources (crt0.S and other sources for statically linking user 37 | programs) there. 38 | 39 | tools: 40 | Native tools (e.g. kernel installers), if any, should be put there. 41 | 42 | user: 43 | Place all sources for userspace programs (e.g. init(1), sh(1)) there. 44 | 45 | -------------------------------------------------------------------------------- /include/sys/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _SYS_TYPES_H 12 | #define _SYS_TYPES_H 13 | 14 | #ifndef __ASSEMBLER__ 15 | /* 16 | * This macro is a wrapper for casting integer constants to unsigned longs, 17 | * freeing the code from compiler warnings and assembler errors (GCC 18 | * warns about shift count if a "UL" suffix is not appended while GAS 19 | * refuses to recognize the "UL" suffix). 20 | */ 21 | #define ULCAST(i) (i##UL) 22 | #else /* __ASSEMBLER__ */ 23 | #define ULCAST(i) i 24 | #endif /* !__ASSEMBLER__ */ 25 | 26 | #ifndef __ASSEMBLER__ 27 | typedef unsigned char uint8, uchar, byte, __u8, u8, uint8_t; 28 | typedef signed char __s8, int8_t; 29 | typedef unsigned short uint16, ushort, __u16, u16, uint16_t; 30 | typedef signed short __s16, int16_t; 31 | typedef unsigned int uint32, uint, __u32, u32, uint32_t; 32 | typedef signed int __s32, int32_t; 33 | typedef unsigned long ulong; 34 | typedef unsigned long long uint64, __u64, u64, uint64_t; 35 | typedef signed long long int64, __s64, int64_t; 36 | typedef unsigned int bool; 37 | #define false 0 38 | #define true 1 39 | 40 | typedef unsigned long size_t; 41 | typedef signed long ssize_t; 42 | 43 | typedef void *uintptr_t; 44 | 45 | #endif 46 | 47 | #endif 48 | 49 | -------------------------------------------------------------------------------- /boot/Makefile.mips64: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015 Gan Quan 2 | # 3 | # This program is free software; you can redistribute it and/or modify it 4 | # under the terms of the GNU General Public License as published by the 5 | # Free Software Foundation; either version 2 of the License, or (at your 6 | # option) any later version. 7 | 8 | # Makefile for MIPS64 9 | 10 | PREFIX = arch/$(ARCH)/$(MACH)/bootsect 11 | 12 | INCFLAG = -I.. -I../include 13 | INCFLAG += -I../include/arch/$(ARCH) 14 | INCFLAG += -I../include/arch/$(ARCH)/asm/mach-$(MACH) 15 | 16 | CFLAGS = -Os -G 0 -g -mno-abicalls -fno-pic -Wall -mabi=32 17 | CFLAGS += -fno-builtin -nostdinc -nostdlib -mips32r2 -EL $(INCFLAG) 18 | CFLAGS += -DMACH_$(UPPERMACH) -DELF64 19 | 20 | OBJS = $(PREFIX).o 21 | LDSCRIPT = $(PREFIX).ld 22 | ELF = $(PREFIX) 23 | BINARY = $(PREFIX).bin 24 | DISASSEMBLY = $(PREFIX).s 25 | 26 | BACKMBR = $(PREFIX).bak.mbr 27 | MBR = $(PREFIX).mbr 28 | ZERO = /dev/zero 29 | 30 | all: $(BINARY) 31 | 32 | $(BINARY): $(OBJS) 33 | $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $(ELF) $(OBJS) 34 | $(OBJCOPY) -O binary $(ELF) $(BINARY) 35 | $(OBJDUMP) -S $(ELF) > $(DISASSEMBLY) 36 | 37 | clean: 38 | rm -f $(OBJS) $(ELF) $(BINARY) $(DISASSEMBLY) $(MBR) 39 | 40 | install: $(BINARY) 41 | $(SUDO) dd if=$(INSTALLDEV) of=$(BACKMBR) bs=512 count=1 42 | dd if=$(ZERO) of=$(MBR) bs=512 count=1 43 | dd if=$(BINARY) of=$(MBR) conv=notrunc 44 | dd if=$(BACKMBR) of=$(MBR) bs=1 skip=446 seek=446 conv=notrunc 45 | $(SUDO) dd if=$(MBR) of=$(INSTALLDEV) bs=512 count=1 conv=notrunc 46 | 47 | .PHONY: all clean install 48 | -------------------------------------------------------------------------------- /drivers/clock/gtc-a9mpcore.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _DRIVERS_CLOCK_GTC_A9MPCORE 12 | #define _DRIVERS_CLOCK_GTC_A9MPCORE 13 | 14 | #include 15 | 16 | #define GTC_OFFSET 0x200 17 | 18 | #ifdef KERNEL 19 | #define GTC_BASE (mpcore_base + GTC_OFFSET) 20 | #else /* KERNEL */ 21 | #define GTC_BASE (MPCORE_PHYSBASE + GTC_OFFSET) 22 | #endif /* KERNEL */ 23 | 24 | u64 gtc_get_time(); 25 | 26 | /* 27 | * ticks per second. 28 | * Zynq7000 is an APSoC and it's got a LOT of clocks. 29 | * GTC's freqency is half of core frequency. 30 | * core freqency is 6x or 8x ARM PLL 31 | * but ARM PLL itself is programmable ... 32 | * we set a LARGE value here to make sure sleep() and usleep() wait 33 | * long enough. 34 | * value here is 400M, means core run at 800MHz. 35 | */ 36 | #define GTC_TPUS 400l 37 | #define GTC_TPS (GTC_TPUS * 1000000l) 38 | /* avoid division whenever possible. 39 | * DO NOT LET OPTIMIZATION DECIDE THIS BEHAVIOR! 40 | */ 41 | 42 | /* register offset */ 43 | #define GTC_COUNTER_LO_OFFSET 0x00 44 | #define GTC_COUNTER_HI_OFFSET 0x04 45 | #define GTC_CTRL_OFFSET 0x08 46 | #define GTC_INT_OFFSET 0x0C 47 | #define GTC_COMPARATOR_LO_OFFSET 0x10 48 | #define GTC_COMPARATOR_HI_OFFSET 0x14 49 | #define GTC_INCREMENT_OFFSET 0x18 50 | 51 | #endif /* _DRIVERS_CLOCK_GTC_A9MPCORE */ 52 | -------------------------------------------------------------------------------- /kern/arch/mips64/include/asm/asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * asmmacro.h: Assembler macros to make things easier to read. 3 | * 4 | * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 5 | * Copyright (C) 1998 Ralf Baechle 6 | * 7 | * Copyright (C) 2015 Gan Quan (coin2028@hotmail.com) 8 | */ 9 | 10 | #ifndef _ASM_ASM_H 11 | #define _ASM_ASM_H 12 | 13 | #include "regdef.h" 14 | #include "cp0regdef.h" 15 | 16 | /* 17 | * LEAF - declare leaf routine 18 | */ 19 | #define LEAF(symbol) \ 20 | .globl symbol; \ 21 | .align 2; \ 22 | .type symbol,@function; \ 23 | .ent symbol,0; \ 24 | symbol: .frame sp,0,ra 25 | 26 | /* 27 | * NESTED - declare nested routine entry point 28 | */ 29 | #define NESTED(symbol, framesize, rpc) \ 30 | .globl symbol; \ 31 | .align 2; \ 32 | .type symbol,@function; \ 33 | .ent symbol,0; \ 34 | symbol: .frame sp, framesize, rpc 35 | 36 | 37 | /* 38 | * END - mark end of function 39 | */ 40 | #define END(function) \ 41 | .end function; \ 42 | .size function,.-function 43 | 44 | /* 45 | * OFFSET - specify address offset of the following code 46 | */ 47 | #define OFFSET(off) \ 48 | .org off; 49 | 50 | /* 51 | * ENTRY, EXIT - define entry and exit of a control block. 52 | * Use LEAF() or NESTED() instead if you want to declare an assembly function. 53 | */ 54 | #define ENTRY(symbol) \ 55 | .ent symbol; 56 | 57 | #define EXIT(symbol) \ 58 | .end symbol; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /kern/arch/mips64/trap/traps.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | /* The entry defined in except.S */ 15 | extern unsigned int except_generic; 16 | 17 | void trap_init(void) 18 | { 19 | /* 20 | * MIPS defined exception handler entries in predefined addresses. 21 | * 22 | * The base address for all handlers is determined by Bootstrap 23 | * Exception Vector (BEV) bit in CP0 status register. If BEV=1, 24 | * the base address would be 0xffffffffbfc00000, otherwise it would 25 | * be 0xffffffff80000000. 26 | * 27 | * For TLB refill exception, the entry address is identical to base 28 | * address. 29 | * 30 | * For 64-bit TLB refill exception, the entry address sometimes could 31 | * be (base + 0x80), but here we copy the TLB refill handler to both 32 | * entries nevertheless. 33 | * 34 | * For cache error exception, the entry is at (base + 0x100). Usually 35 | * this error should not happen, especially when cache coherency is 36 | * maintained by hardware, such as Loongson 3A. 37 | * 38 | * All other exceptions, as well as interrupts, system calls, etc., 39 | * have their entries located at (base + 0x180). 40 | */ 41 | 42 | /* 43 | * We temporarily use generic handler for TLB exceptions. 44 | * Will be changed when implementing memory management. 45 | */ 46 | memcpy((void *)EXCEPT_TLB, &except_generic, 0x80); 47 | memcpy((void *)EXCEPT_TLBX, &except_generic, 0x80); 48 | memcpy((void *)EXCEPT_CACHEERR, &except_generic, 0x80); 49 | memcpy((void *)EXCEPT_GENERIC, &except_generic, 0x80); 50 | } 51 | 52 | /* Generic C exception handler */ 53 | void handle_exception(struct trapframe *tf) 54 | { 55 | } 56 | -------------------------------------------------------------------------------- /lib/libc/string/memset.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1990 The Regents of the University of California. 3 | * All rights reserved. 4 | * 5 | * This code is derived from software contributed to Berkeley by 6 | * Chris Torek. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of the University nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 | * SUCH DAMAGE. 31 | */ 32 | 33 | #include 34 | 35 | void * 36 | memset(void *dst, int c, size_t n) 37 | { 38 | if (n != 0) { 39 | unsigned char *d = dst; 40 | 41 | do 42 | *d++ = (unsigned char)c; 43 | while (--n != 0); 44 | } 45 | return (dst); 46 | } 47 | -------------------------------------------------------------------------------- /drivers/ata/ahci_cmd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | /* 12 | * This header contains SATA command structures and constants. 13 | * 14 | * References: 15 | * SATA 1.3 specification, available on Intel's website. 16 | */ 17 | 18 | #ifndef _DRIVERS_ATA_AHCI_CMD_H 19 | #define _DRIVERS_ATA_AHCI_CMD_H 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | /* PRD - Physical Region Descriptor */ 26 | struct ahci_prd { 27 | uint dba; 28 | uint dbau; 29 | uint reserved; 30 | uint dbc:22; /* Data bytes minus 1 */ 31 | uint reserved2:9; 32 | uint intr:1; 33 | }; 34 | 35 | /* 36 | * Command Table 37 | * 38 | * The command table header is followed by a list of @prdtl PRDs. 39 | */ 40 | struct ahci_cmdtbl { 41 | union { 42 | struct fis_reg_h2d cfis; 43 | uchar cfis_buf[64]; 44 | }; 45 | union { 46 | uchar acmd_buf[16]; 47 | }; 48 | uchar reserved[48]; 49 | }; 50 | 51 | struct ahci_cmdhdr { 52 | /* DWORD 0 */ 53 | uchar cfl:5; 54 | uchar atapi:1; 55 | uchar write:1; 56 | uchar prefetch:1; 57 | uchar reset:1; 58 | uchar bist:1; 59 | uchar clear_on_ok:1; 60 | uchar rsvd:1; 61 | uchar pmp:4; 62 | ushort prdtl; /* Should not exceed 8 */ 63 | /* DWORD 1 */ 64 | uint prdbc; 65 | /* DWORD 2-3 */ 66 | uint ctba; 67 | uint ctbau; 68 | /* DWORD 4-7 */ 69 | uint reserved[4]; 70 | }; 71 | 72 | struct ahci_cmdslot { 73 | struct ahci_cmdtbl ct; 74 | struct ahci_prd prd[8]; 75 | }; 76 | 77 | #define AHCI_DATA_SIZE 0x200 /* 1 sector */ 78 | #define AHCI_CMDDESCLIST_SIZE 0x2000 /* See ahci.h */ 79 | #define AHCI_CMDDATALIST_SIZE 0x4000 /* 32 x Data FIS size */ 80 | #define AHCI_CMDLIST_SIZE 0x400 /* 32 x sizeof(ahci_cmdhdr) */ 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /drivers/ata/ahci.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _DRIVERS_ATA_AHCI_H 12 | #define _DRIVERS_ATA_AHCI_H 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | int ahci_init_port(volatile struct ahci_hba_port *port, unsigned int *serror); 19 | 20 | /* 21 | * See asm/addrspace.h for physical address space layout 22 | */ 23 | 24 | /* 25 | * Host memory layout for AHCI: 26 | * 27 | * Single port: 28 | * +-----------------------+ 0 29 | * |Command 1 Table Header| 30 | * +-----------------------+ 0x80 31 | * |Command 1 PRD x 8 | 32 | * +-----------------------+ 0x100 33 | * |Command 2 Table Header| 34 | * +-----------------------+ 0x180 35 | * |Command 2 PRD x 8 | 36 | * +-----------------------+ 0x200 37 | * |... (32 command tables)| 38 | * +-----------------------+ 0x2000 <--- DATA 39 | * | Command 1 Data | 40 | * +-----------------------+ 0x2200 41 | * | Command 2 Data | 42 | * +-----------------------+ 0x2400 43 | * | ... (32 command data) | 44 | * +=======================+ 0x6000 <--- CLB 45 | * |Command Header 1| 46 | * +-----------------------+ 0x6020 47 | * |Command Header 2| 48 | * +-----------------------+ 0x6040 49 | * |...(32 command headers)| 50 | * +=======================+ 0x6400 <--- FB 51 | * |FIS Receive Buffer| 52 | * +=======================+ 0x6500 53 | * | Reserved | 54 | * +-----------------------+ 0x8000 55 | */ 56 | #define AHCI_OFFSET 0x100000 57 | #define AHCIPHY (DMAPHY + AHCI_OFFSET) 58 | #define AHCI_PORT_RAM_SIZE 0x8000 59 | #define AHCI_DATA_OFFSET 0x2000 60 | #define AHCI_CLB_OFFSET 0x6000 61 | #define AHCI_FB_OFFSET 0x6400 62 | 63 | extern unsigned int hba_ports_available; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /drivers/serial/uart-zynq7000.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | 13 | #ifdef UART_ZYNQ7000 14 | 15 | #include 16 | 17 | #include 18 | 19 | void uart_init(void) 20 | { 21 | /* Disable interrupts */ 22 | out32(UART_BASE + UART_OFFSET_IDR, UART_IXR_MASK); 23 | /* Disable TX and RX */ 24 | uart_disable(); 25 | /* Reset TX and RX, Clear FIFO */ 26 | out32(UART_BASE + UART_OFFSET_CR, UART_CR_TXRST | UART_CR_RXRST); 27 | /* Clear Flags */ 28 | out32(UART_BASE + UART_OFFSET_ISR, UART_IXR_MASK); 29 | /* Mode Reset to Normal/8-N-1 */ 30 | out32(UART_BASE + UART_OFFSET_MR, 31 | UART_MR_CHMODE_NORM | UART_MR_CHARLEN_8_BIT | 32 | UART_MR_PARITY_NONE | UART_MR_STOPMODE_1_BIT); 33 | /* Trigger Reset */ 34 | out32(UART_BASE + UART_OFFSET_RXWM, UART_RXWM_RESET_VAL); 35 | out32(UART_BASE + UART_OFFSET_TXWM, UART_TXWM_RESET_VAL); 36 | /* Disable RX timeout */ 37 | out32(UART_BASE + UART_OFFSET_RXTOUT, UART_RXTOUT_DISABLE); 38 | /* Reset baud rate generator and divider to genetate 115200 */ 39 | out32(UART_BASE + UART_OFFSET_BAUDGEN, 0x3E); 40 | out32(UART_BASE + UART_OFFSET_BAUDDIV, 0x06); 41 | /* Set CR Value */ 42 | out32(UART_BASE + UART_OFFSET_CR, 43 | UART_CR_RX_DIS | UART_CR_TX_DIS | UART_CR_STOPBRK); 44 | } 45 | 46 | void uart_enable(void) 47 | { 48 | /* Enable TX and RX */ 49 | out32(UART_BASE + UART_OFFSET_CR, UART_CR_TX_EN | UART_CR_RX_EN); 50 | } 51 | 52 | void uart_disable(void) 53 | { 54 | /* Disable TX and RX */ 55 | out32(UART_BASE + UART_OFFSET_CR, UART_CR_TX_DIS | UART_CR_RX_DIS); 56 | } 57 | 58 | unsigned char uart_spin_getbyte(void) 59 | { 60 | while (in32(UART_BASE + UART_OFFSET_SR) & UART_SR_RXEMPTY); 61 | return in32(UART_BASE + UART_OFFSET_FIFO); 62 | } 63 | 64 | void uart_spin_putbyte(unsigned char byte) 65 | { 66 | while (in32(UART_BASE + UART_OFFSET_SR) & UART_SR_TXFULL); 67 | out32(UART_BASE + UART_OFFSET_FIFO, byte); 68 | } 69 | 70 | #endif /* UART_ZYNQ7000 */ 71 | -------------------------------------------------------------------------------- /firmware/arch/armv7a-le/bootmain.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | void puthex(u32 num) 18 | { 19 | int i; 20 | const char table[] = "0123456789ABCDEF"; 21 | char buf[11] = "00000000\r\n"; 22 | for (i = 28; i >= 0; i -= 4){ 23 | buf[(28 - i) >> 2] = table[(num >> i) & 0xF]; 24 | } 25 | uart_spin_puts(buf); 26 | } 27 | 28 | void firmware_bootmain(void) 29 | { 30 | int ret; 31 | volatile u8 *mbr = (void *)0x100000; /* THIS IS NOT A NULL! */ 32 | void (*mbr_entry)() = (void *)mbr; 33 | 34 | /* Wait for UART fifo to flush */ 35 | sleep(1); 36 | 37 | /* Initialize and enable UART */ 38 | uart_init(); 39 | uart_enable(); 40 | uart_spin_puts("FW: Hello!\r\n"); 41 | 42 | /* Initialize SDHCI interface */ 43 | sd_init(); 44 | uart_spin_puts("FW: SD Controller initialized.\r\n"); 45 | 46 | /* Initialize SD card */ 47 | ret = sd_spin_init_mem_card(); 48 | if (ret == 0) uart_spin_puts("FW: SD Card initialized.\r\n"); 49 | else if (ret == 1) uart_spin_puts("FW: SDHC Card initialized.\r\n"); 50 | else { 51 | uart_spin_puts("FW: Card initialization failed.\r\n"); 52 | goto spin; 53 | } 54 | 55 | /* 56 | * We don't turn on SCU now. The kernel should do this. 57 | * This CANNOT be done here. DDR in 0x0 to 0xFFFFF is only accessible 58 | * to processor cores, not the DMA controller. 59 | * See Xilinx UG585, Table 4-1 for details. 60 | */ 61 | 62 | /* Read MBR */ 63 | ret = sd_dma_spin_read((u32)mbr, 1, 0); 64 | if (ret == 0) uart_spin_puts("FW: Card read OK.\r\n"); 65 | else { 66 | uart_spin_puts("FW: Card read failed.\r\n"); 67 | goto spin; 68 | } 69 | 70 | /* Check MBR */ 71 | if (mbr[510] == 0x55 && mbr[511] == 0xAA) { 72 | uart_spin_puts("FW: MBR valid.\r\n"); 73 | mbr_entry(); 74 | } else uart_spin_puts("FW: MBR not valid.\r\n"); 75 | 76 | spin: 77 | while (1); 78 | } 79 | 80 | -------------------------------------------------------------------------------- /include/device.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _DEVICE_H 12 | #define _DEVICE_H 13 | 14 | #include 15 | 16 | enum device_type { 17 | DEV_KBD, /* Keyboard */ 18 | DEV_LP, /* Printer (MSIM) */ 19 | DEV_VGA, /* VGA (QEMU) */ 20 | DEV_HD, /* Hard disk (MSIM, QEMU, Loongson, ZYNQ) */ 21 | DEV_SERIAL, /* Serial */ 22 | DEV_MPHUB, /* Multi-processor Hub */ 23 | }; 24 | 25 | /* 26 | * Usage of struct device: 27 | * 28 | * This is a header structure for all device structures. 29 | * For example, one can define a structure: 30 | * struct hd { 31 | * struct device dev; 32 | * uint32_t size; 33 | * ... 34 | * } 35 | * Then a pointer of "struct device" could also point to "struct hd". 36 | */ 37 | struct device { 38 | /* 39 | * See major(3) and minor(3) for definition of major device number 40 | * and minor device number. 41 | */ 42 | uint16_t major; 43 | uint16_t minor; 44 | uint16_t type; /* really should be enum device_type */ 45 | uint16_t irq_no; /* negative for no IRQ */ 46 | uint32_t function; 47 | #define DEVFUNC_LINE_OUTPUT 0x1 48 | #define DEVFUNC_STORAGE 0x2 49 | #define DEVFUNC_KEYBOARD 0x4 50 | uint32_t status; 51 | #define DEVSTAT_AVAILABLE 0x1 52 | unsigned long phys_addr; /* Device physical address */ 53 | }; 54 | 55 | /* 56 | * TODO: 57 | * @davidgao @raysmond 58 | * How shall we dispatch interrupts? 59 | * i386 has IRQs, 60 | * MIPS cores have 8 interrupt lines, 61 | * I wonder how ARM handles interrupts, and how shall we bend everything 62 | * together. 63 | * I guess the workflow should involve some interrupt handler registeration. 64 | */ 65 | 66 | struct device_intr_handler { 67 | bool (*check)(struct device *); 68 | void (*ack)(struct device *); 69 | }; 70 | 71 | /* 72 | * Note: 73 | * Later the content inside the device array would be dynamically allocated, 74 | * after we implement kmalloc(). 75 | * Maybe we should implement devs as a list instead. 76 | */ 77 | extern struct device *devs[]; /* Indexed by major device # */ 78 | extern unsigned int ndevs; /* Number of devices registered */ 79 | 80 | /* Register a device into device list "devs" */ 81 | void device_register(struct device *dev); 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /Makefile.armv7a-le: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015 David Gao 2 | # 3 | # This program is free software; you can redistribute it and/or modify it 4 | # under the terms of the GNU General Public License as published by the 5 | # Free Software Foundation; either version 2 of the License, or (at your 6 | # option) any later version. 7 | 8 | # Makefile for ARMv7A-LE 9 | 10 | ######## BEGIN CONFIG ######## 11 | CROSS_COMPILE = arm-unknown-eabi- 12 | 13 | MACH = zynq7000 14 | BOARD = zedboard 15 | ######## END CONFIG ######## 16 | 17 | ROOTDIR = $(shell pwd) 18 | UPPERMACH = $(shell echo $(MACH) | tr a-z- A-Z_) 19 | 20 | M4 = m4 21 | CC = $(CROSS_COMPILE)gcc 22 | CPP = $(CROSS_COMPILE)cpp 23 | LD = $(CROSS_COMPILE)ld 24 | OBJDUMP = $(CROSS_COMPILE)objdump 25 | OBJCOPY = $(CROSS_COMPILE)objcopy 26 | 27 | INCFLAG = -I. -I./include -I./include/arch/$(ARCH) 28 | INCFLAG += -I./include/arch/$(ARCH)/asm/mach-$(MACH) 29 | 30 | CFLAGS = -Wall -fno-builtin -nostdinc -nostdlib -march=armv7-a 31 | CFLAGS += -mlittle-endian $(INCFLAG) -DMACH_$(UPPERMACH) 32 | 33 | LDFLAGS = -EL -O -N 34 | 35 | FIRMWARE_OBJS = firmware/arch/$(ARCH)/vector.o \ 36 | firmware/arch/$(ARCH)/bootasm.o \ 37 | firmware/arch/$(ARCH)/bootmain.o \ 38 | drivers/serial/uart-zynq7000.o \ 39 | drivers/serial/uart.o \ 40 | drivers/clock/gtc-a9mpcore.o \ 41 | drivers/sd/sd-zynq7000.o 42 | 43 | FIRMWARE_M4 = firmware/arch/$(ARCH)/firmware.m4 \ 44 | firmware/arch/$(ARCH)/$(MACH)/chip.m4 \ 45 | firmware/arch/$(ARCH)/$(MACH)/$(BOARD)/board.m4 46 | 47 | MBR_OBJS = boot/arch/$(ARCH)/$(MACH)/bootmain.o 48 | 49 | all: firmware.bin mbr.bin 50 | 51 | $(FIRMWARE_OBJS): EXTRA_CFLAGS = -O2 52 | 53 | firmware.ld: $(FIRMWARE_M4) 54 | $(M4) firmware/arch/$(ARCH)/firmware.m4 \ 55 | -I firmware/arch/$(ARCH)/$(MACH)/ \ 56 | -I firmware/arch/$(ARCH)/$(MACH)/$(BOARD)/ > $@ 57 | 58 | firmware.elf: $(FIRMWARE_OBJS) firmware.ld 59 | $(LD) $(LDFLAGS) -T firmware.ld -o $@ $(FIRMWARE_OBJS) 60 | 61 | $(MBR_OBJS): EXTRA_CFLAGS := -Os 62 | 63 | mbr.elf: $(MBR_OBJS) boot/arch/$(ARCH)/$(MACH)/mbr.ld 64 | $(LD) $(LDFLAGS) -T boot/arch/$(ARCH)/$(MACH)/mbr.ld -o $@ $^ 65 | 66 | clean: 67 | rm -f firmware.ld 68 | rm -rf $(FIRMWARE_OBJS) firmware.elf firmware.bin firmware.s 69 | rm -rf $(MBR_OBJS) mbr.elf mbr.bin mbr.s 70 | 71 | .S.o: 72 | $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< 73 | 74 | .c.o: 75 | $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< 76 | 77 | %.s: %.elf 78 | $(OBJDUMP) -S $^ > $@ 79 | 80 | %.bin: %.elf 81 | $(OBJCOPY) -O binary -S $^ $@ 82 | 83 | .PHONY: clean 84 | -------------------------------------------------------------------------------- /include/stab.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Chen Yu 3 | * Copyright (C) 2015 Gan Quan 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or (at your 8 | * option) any later version. 9 | * 10 | */ 11 | 12 | #ifndef _STAB_H 13 | #define _STAB_H 14 | 15 | #include 16 | 17 | /* 18 | * STABS debugging info 19 | * 20 | * The kernel debugger can understand some debugging information in 21 | * the STABS format. For more information on this format, see 22 | * http://sources.redhat.com/gdb/onlinedocs/stabs_toc.html 23 | * 24 | * The constants below define some symbol types used by various debuggers 25 | * and compilers. Kernel uses the N_SO, N_SOL, N_FUN, and N_SLINE types. 26 | */ 27 | 28 | #define N_GSYM 0x20 /* global symbol */ 29 | #define N_FNAME 0x22 /* F77 function name */ 30 | #define N_FUN 0x24 /* procedure name */ 31 | #define N_STSYM 0x26 /* data segment variable */ 32 | #define N_LCSYM 0x28 /* bss segment variable */ 33 | #define N_MAIN 0x2a /* main function name */ 34 | #define N_PC 0x30 /* global Pascal symbol */ 35 | #define N_RSYM 0x40 /* register variable */ 36 | #define N_SLINE 0x44 /* text segment line number */ 37 | #define N_DSLINE 0x46 /* data segment line number */ 38 | #define N_BSLINE 0x48 /* bss segment line number */ 39 | #define N_SSYM 0x60 /* structure/union element */ 40 | #define N_SO 0x64 /* main source file name */ 41 | #define N_LSYM 0x80 /* stack variable */ 42 | #define N_BINCL 0x82 /* include file beginning */ 43 | #define N_SOL 0x84 /* included source file name */ 44 | #define N_PSYM 0xa0 /* parameter variable */ 45 | #define N_EINCL 0xa2 /* include file end */ 46 | #define N_ENTRY 0xa4 /* alternate entry point */ 47 | #define N_LBRAC 0xc0 /* left bracket */ 48 | #define N_EXCL 0xc2 /* deleted include file */ 49 | #define N_RBRAC 0xe0 /* right bracket */ 50 | #define N_BCOMM 0xe2 /* begin common */ 51 | #define N_ECOMM 0xe4 /* end common */ 52 | #define N_ECOML 0xe8 /* end common (local name) */ 53 | #define N_LENG 0xfe /* length of preceding entry */ 54 | 55 | /* Entries in the STABS table are formatted as follows. */ 56 | struct stab { 57 | uint32_t n_strx; /* index into string table of name */ 58 | uint8_t n_type; /* type of symbol */ 59 | uint8_t n_other; /* misc info (usually empty) */ 60 | uint16_t n_desc; /* description field */ 61 | uint32_t n_value; /* value of symbol */ 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /doc/booting.markdown: -------------------------------------------------------------------------------- 1 | # Booting 2 | 3 | Booting process, which deals with associated hardware, is inevitably 4 | machine-specific. Here are the booting processes on different machine 5 | configurations available to us. 6 | 7 | ### i386/QEMU 8 | 9 | The only thing we care is bootloader since most work is done by SeaBIOS. 10 | 11 | ### arm/Zedboard 12 | 13 | Booting on zedboard includes multiple stages. 14 | 15 | * Stage 0, on-chip bootROM, poorly documented, possibly executed in-place. 16 | Programmers have NO access to this ROM. It writes basic configuration to the 17 | processing system (PS) but not programmable logic (PL), making basic peripherals 18 | accessible, loads boot image from media (according to jumper values), and handoff 19 | to first-stage bootloader (FSBL) inside the image. 20 | * Stage 1, FSBL, loaded into OCM. Should program PS and PL (even if it is blank), 21 | load next stage and handoff. 22 | * Stage 2, SSBL or second-stage bootloader, loaded into DDR. Should find kernel, 23 | load it and boot it. 24 | 25 | Our design is to build a basic FSBL, which reads MBR on SD card, verify its magic, 26 | and handoff. This FSBL should eventually end up in QSPI flash to save a boot flag 27 | (Because bootROM's exact behavior is undocumented), but currently a file in the 28 | FAT32 partition is just okay. 29 | 30 | Our SSBL should start from MBR, and from this point on everything should be unified 31 | across platforms and devices. 32 | 33 | ### mips64/Loongson3A 34 | 35 | Loongson Tech provided a box dubbed 3A-MATX with PMON code shipped 36 | at (TODO: upload PMON patch and source code, which isn't included on Loongson's 37 | website). I modified the `main` subroutine of PMON to load and jump to MBR. 38 | 39 | The bootstrapper code in MBR demands extreme care, and is nearly-impossible to 40 | code without existing helper functions (such as `open`, `read`, `puts`, etc., 41 | which is already provided in PMON, which made me ultimately decide to modify 42 | PMON despite its ~~crappy~~ unfavorable code style instead of writing my own 43 | from scratch). 44 | 45 | ### MBR 46 | 47 | The MBR records four main partitions: 48 | 49 | * The first one is reserved for an existing commonly-used partition such as FAT 50 | (for Zedboard) or ext2 (shipped with Loongson-3A) due to compatibility. 51 | * The second one is a small partition with boot flag and an "unknown" partition 52 | type `0xd0` (one can invoke `fdisk(8)` to view the list of known partition 53 | types), containing our kernel. 54 | * The third one is a fairly-sized partition which is for swapping. Its type 55 | is again a different "unknown" one `0xd1`. 56 | * The fourth one is our customized file system. its type is an another unknown 57 | one `0xd2`, different from the second and third partition. 58 | 59 | -------------------------------------------------------------------------------- /kern/FILES: -------------------------------------------------------------------------------- 1 | More suggestions are welcome. 2 | 3 | kern: 4 | All kernel-related sources and headers should be here. 5 | 6 | kern/arch/$(ARCH): 7 | Architecture dependent sources, including trap handling, context switches, etc. 8 | should go there. 9 | 10 | kern/arch/$(ARCH)/$(MACH): 11 | For machine dependent sources. 12 | 13 | kern/arch/$(ARCH)/include/asm: 14 | For architecture-dependent headers. 15 | 16 | kern/arch/$(ARCH)/include/asm/mach-$(MACH): 17 | For machine-dependent headers. 18 | 19 | kern/fs: 20 | Source codes about filesystems should go there. 21 | 22 | kern/include: 23 | Kernel-specific headers should go there. Module-specific sub-directories are 24 | recommended. 25 | Architecture-dependent headers should go inside kern/arch/$(ARCH)/include/asm 26 | rather than kern/include. 27 | 28 | kern/arch/$(ARCH)/mm, kern/mm: 29 | Memory management, including memory allocators, both physical and virtual. 30 | 31 | The physical memory allocator should expose the following structure: 32 | 33 | struct page 34 | For physical page representation 35 | 36 | and the following interfaces: 37 | 38 | alloc_pages(int num) 39 | Allocate @num pages. 40 | free_pages(struct page *p, int num) 41 | Free @num pages starting from @p. 42 | 43 | The virtual memory allocator should expose the following interfaces: 44 | 45 | kmalloc(size_t size) 46 | Allocate @size bytes. 47 | kfree(void *ptr) 48 | Free an allocation including @ptr. 49 | 50 | and can optionally include kernel equivalents of calloc(3) and realloc(3). 51 | 52 | See kern/mm/DESIGN for my (BarclayII's) current design of memory allocators. 53 | 54 | The memory management module should expose the following structure: 55 | 56 | struct mm_struct 57 | A per-process structure containing memory mapping etc. 58 | 59 | kern/arch/$(ARCH)/sched, kern/sched: 60 | Scheduler-related sources, including process (and thread, if any) management, 61 | should go there. 62 | 63 | The scheduler should declare the following structures: 64 | 65 | struct task_struct 66 | For denoting a process (or thread, if any). 67 | 68 | and either of the following structures: 69 | 70 | struct cpu_run_queue 71 | For denoting a run queue on a single CPU. 72 | struct run_queue 73 | For denoting a run queue shared over all CPUs. 74 | 75 | and the following interfaces: 76 | 77 | cpurq_enqueue(struct cpu_run_queue *rq, struct task_struct *t) 78 | Insert task @t into run queue @rq. 79 | cpurq_dequeue(struct task_struct *t) 80 | Remove task @t from the queue it resides in. 81 | cpurq_pick_next(struct cpu_run_queue *rq) 82 | Return the next task to be run in @rq. Does *not* pop the 83 | task. 84 | cpurq_tick(struct task_struct *t) 85 | Indicates a tick of execution of @t. 86 | 87 | or the run_queue variants. 88 | 89 | kern/sync: 90 | Synchronization-related sources (spinlocks, semaphores etc.) should go there. 91 | 92 | -------------------------------------------------------------------------------- /drivers/misc/dtb-zynq7000.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #define _DTB_C 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | u32 ocm_base = OCM_PHYSBASE_LO; 18 | u32 ddr_base = DDR_PHYSBASE_SCU; 19 | u32 axi_gp0_base = AXI_GP0_PHYSBASE; 20 | u32 axi_gp1_base = AXI_GP1_PHYSBASE; 21 | u32 qspi_linear_base = QSPI_LINEAR_PHYSBASE; 22 | 23 | u32 ddr_end = DDR_PHYSEND; 24 | 25 | u32 uart0_base = UART0_PHYSBASE; 26 | u32 uart1_base = UART1_PHYSBASE; 27 | u32 usb0_base = USB0_PHYSBASE; 28 | u32 usb1_base = USB1_PHYSBASE; 29 | u32 i2c0_base = I2C0_PHYSBASE; 30 | u32 i2c1_base = I2C1_PHYSBASE; 31 | u32 spi0_base = SPI0_PHYSBASE; 32 | u32 spi1_base = SPI1_PHYSBASE; 33 | u32 can0_base = CAN0_PHYSBASE; 34 | u32 can1_base = CAN1_PHYSBASE; 35 | u32 gpio_base = GPIO_PHYSBASE; 36 | u32 gem0_base = GEM0_PHYSBASE; 37 | u32 gem1_base = GEM1_PHYSBASE; 38 | u32 qspi_base = QSPI_PHYSBASE; 39 | u32 smcc_base = SMCC_PHYSBASE; 40 | 41 | u32 sd0_base = SD0_PHYSBASE; 42 | u32 sd1_base = SD1_PHYSBASE; 43 | 44 | u32 smc_nand_base = SMC_NAND_PHYSBASE; 45 | u32 smc_sram0_base = SMC_SRAM0_PHYSBASE; 46 | u32 smc_sram1_base = SMC_SRAM1_PHYSBASE; 47 | 48 | u32 slcr_base = SLCR_PHYSBASE; 49 | u32 ttc0_base = TTC0_PHYSBASE; 50 | u32 ttc1_base = TTC1_PHYSBASE; 51 | u32 dmac0_s_base = DMAC0_S_PHYSBASE; 52 | u32 dmac0_ns_base = DMAC0_NS_PHYSBASE; 53 | u32 swdt_base = SWDT_PHYSBASE; 54 | u32 ddrc_base = DDRC_PHYSBASE; 55 | u32 devcfg_base = DEVCFG_PHYSBASE; 56 | u32 axi_hp0_base = AXI_HP0_PHYSBASE; 57 | u32 axi_hp1_base = AXI_HP1_PHYSBASE; 58 | u32 axi_hp2_base = AXI_HP2_PHYSBASE; 59 | u32 axi_hp3_base = AXI_HP3_PHYSBASE; 60 | u32 ocmc_base = OCMC_PHYSBASE; 61 | 62 | u32 debug_dap_rom_base = DEBUG_DAP_ROM_PHYSBASE; 63 | u32 debug_etb_base = DEBUG_ETB_PHYSBASE; 64 | u32 debug_cti_etb_tpiu_base = DEBUG_CTI_ETB_TPIU_PHYSBASE; 65 | u32 debug_tpiu_base = DEBUG_TPIU_PHYSBASE; 66 | u32 debug_funnel_base = DEBUG_FUNNEL_PHYSBASE; 67 | u32 debug_itm_base = DEBUG_ITM_PHYSBASE; 68 | u32 debug_cti_ftm_base = DEBUG_CTI_FTM_PHYSBASE; 69 | u32 debug_ftm_base = DEBUG_FTM_PHYSBASE; 70 | 71 | u32 debug_cpu_pmu0_base = DEBUG_CPU_PMU0_PHYSBASE; 72 | u32 debug_cpu_pmu1_base = DEBUG_CPU_PMU1_PHYSBASE; 73 | u32 debug_cpu_cti0_base = DEBUG_CPU_CTI0_PHYSBASE; 74 | u32 debug_cpu_cti1_base = DEBUG_CPU_CTI1_PHYSBASE; 75 | u32 debug_cpu_ptm0_base = DEBUG_CPU_PTM0_PHYSBASE; 76 | u32 debug_cpu_ptm1_base = DEBUG_CPU_PTM1_PHYSBASE; 77 | 78 | u32 gpv_trustzone_base = GPV_TRUSTZONE_PHYSBASE; 79 | u32 gpv_qos301_cpu_base = GPV_QOS301_CPU_PHYSBASE; 80 | u32 gpv_qos301_dmac_base = GPV_QOS301_DMAC_PHYSBASE; 81 | u32 gpv_qos301_iou_base = GPV_QOS301_IOU_PHYSBASE; 82 | 83 | u32 mpcore_base = MPCORE_PHYSBASE; 84 | u32 l2cache_base = L2CACHE_PHYSBASE; 85 | -------------------------------------------------------------------------------- /kern/arch/mips64/trap/except.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | NESTED(except_generic, TF_SIZE, sp) 16 | .set push 17 | .set noat 18 | .set noreorder 19 | /* 20 | * I saved everything we need into a trap frame, then deal with the 21 | * exception in C code. 22 | * 23 | * This is to leave as much work to C as possible. 24 | * 25 | * MIPS specifications require that exception handler entry should 26 | * take at most 128 bytes, hence the jump. 27 | */ 28 | j handle_exception_entry 29 | nop 30 | .set pop 31 | END(except_generic) 32 | 33 | handle_exception_entry: 34 | .set push 35 | .set noat 36 | /* 37 | * Save all registers and coprocessor registers we need. The list 38 | * include but is probably not limited to: 39 | * 1. GPRs, except k0 and k1 reserved for exception handler, which 40 | * is usually not saved. 41 | * 2. CP0 status register, indicating current CPU working state. 42 | * 3. CP0 cause register, storing the cause of exception or interrupt, 43 | * and whether the victim instruction is in a branch delay slot. 44 | * 4. CP0 exception program counter (EPC) register, showing the 45 | * address of instruction which threw an exception (the victim 46 | * instruction). 47 | * 5. CP0 bad virtual address (BADVADDR) register, which stores the 48 | * memory address the processor tries to access if the exception 49 | * is an access violation. 50 | * 6. CP0 ENTRYLO0, ENTRYLO1, and ENTRYHI registers, in case of a 51 | * failed TLB refill (will be covered in later labs). 52 | * 53 | * The macro SAVE_ALL defined in asm/stackframe.h allocates a 54 | * trap frame structure on kernel stack and stores everything we need 55 | * there. 56 | * The macro RESTORE_ALL_AND_RET restores the registers from the 57 | * trap frame and return from exception handler via ERET instruction, 58 | * which does the following atomically (or simultaneously in one 59 | * cycle): 60 | * 1. Turning off exception level bit (EXL) and error level bit (ERL), 61 | * both bits forcing the processor to run in kernel mode regardless 62 | * of the KSU bits. 63 | * 2. Restoring program counter from EPC register. 64 | */ 65 | SAVE_ALL 66 | /* 67 | * Turn Exception Level off and kernel mode on to deal with nested 68 | * exceptions, as the processor won't save victim instruction 69 | * address into EPC register when EXL=1. 70 | */ 71 | mfc0 k0, CP0_STATUS 72 | ori k0, ST_EXCM 73 | xori k0, ST_EXCM 74 | mtc0 k0, CP0_STATUS 75 | /* 76 | * Here JAL transfer handling to C function handle_exception(), with 77 | * its only argument stored in register a0, which is equal to sp, 78 | * pointing to the trap frame structure. 79 | */ 80 | move a0, sp 81 | jal handle_exception 82 | RESTORE_ALL_AND_RET 83 | .set pop 84 | 85 | 86 | -------------------------------------------------------------------------------- /lib/libc/string/memcpy.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1990 The Regents of the University of California. 3 | * All rights reserved. 4 | * 5 | * This code is derived from software contributed to Berkeley by 6 | * Chris Torek. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of the University nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 | * SUCH DAMAGE. 31 | */ 32 | 33 | #include 34 | #include 35 | 36 | /* 37 | * sizeof(word) MUST BE A POWER OF TWO 38 | * SO THAT wmask BELOW IS ALL ONES 39 | */ 40 | typedef long word; /* "word" used for optimal copy speed */ 41 | 42 | #define wsize sizeof(word) 43 | #define wmask (wsize - 1) 44 | 45 | /* 46 | * Copy a block of memory, not handling overlap. 47 | */ 48 | void * 49 | memcpy(void *dst0, const void *src0, size_t length) 50 | { 51 | char *dst = dst0; 52 | const char *src = src0; 53 | size_t t; 54 | 55 | if (length == 0 || dst == src) /* nothing to do */ 56 | goto done; 57 | 58 | /* 59 | * Macros: loop-t-times; and loop-t-times, t>0 60 | */ 61 | #define TLOOP(s) if (t) TLOOP1(s) 62 | #define TLOOP1(s) do { s; } while (--t) 63 | 64 | /* 65 | * Copy forward. 66 | */ 67 | t = (long)src; /* only need low bits */ 68 | if ((t | (long)dst) & wmask) { 69 | /* 70 | * Try to align operands. This cannot be done 71 | * unless the low bits match. 72 | */ 73 | if ((t ^ (long)dst) & wmask || length < wsize) 74 | t = length; 75 | else 76 | t = wsize - (t & wmask); 77 | length -= t; 78 | TLOOP1(*dst++ = *src++); 79 | } 80 | /* 81 | * Copy whole words, then mop up any trailing bytes. 82 | */ 83 | t = length / wsize; 84 | TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize); 85 | t = length & wmask; 86 | TLOOP(*dst++ = *src++); 87 | done: 88 | return (dst0); 89 | } 90 | -------------------------------------------------------------------------------- /kern/debug/debug_info.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* 18 | * Value field of stabs representing address is not always aligned to 4 19 | * bytes on at least MIPS. Not sure whether it's true on ARM. 20 | * asm/util.h is for fixing the address alignment of instructions. 21 | * 22 | * Please provide feedback. 23 | */ 24 | #include 25 | 26 | extern struct stab __STAB_BEGIN__[], __STAB_END__[]; 27 | extern char __STABSTR_BEGIN__[], __STABSTR_END__[]; 28 | 29 | /* 30 | * Find the source file stab by checking the type field. 31 | * All source file stabs with type N_SO and desc field 0 should be ignored 32 | * as they either contain null string or holds the file name of temporary 33 | * overall assembly. 34 | */ 35 | static inline bool is_source(struct stab *stab) 36 | { 37 | return ((stab->n_type == N_SO && stab->n_desc != 0) || 38 | (stab->n_type == N_SOL)); 39 | } 40 | 41 | static inline bool is_textline(struct stab *stab) 42 | { 43 | return (stab->n_type == N_SLINE); 44 | } 45 | 46 | static inline bool is_func(struct stab *stab) 47 | { 48 | return (stab->n_type = N_FUN); 49 | } 50 | 51 | /* 52 | * Get debug info of an instruction 53 | * 54 | * Note that GCC is an optimizing compiler: GCC may arrange, add, and/or 55 | * remove instructions for performance, thus messing the instruction 56 | * structure of function. For example, there may be multiple 57 | * rets in one function in i386 disassembly. 58 | * 59 | * Perhaps the best solution is to perform linear search in the stabs 60 | * section, as stabs are actually not ordered by address. 61 | * 62 | * Parameters: 63 | * @addr : Instruction address 64 | * @info : Debug info structure 65 | * @last : Last stab with the same instruction address 66 | * 67 | * Return value: 68 | * >0 if found. 69 | * 0 if no stab left. 70 | * <0 if didn't find any. 71 | */ 72 | int get_debug_info(uintptr_t addr, struct debug_info *info, struct stab **last) 73 | { 74 | struct stab *cur_stab; 75 | char *source_filename = NULL, *func_name = NULL; 76 | unsigned int source_addr32 = 0, func_addr32 = 0, line_addr32 = 0; 77 | unsigned int addr32 = lo32((unsigned long)addr); 78 | bool found = false; 79 | 80 | addr32 = FIX_INSTRUCTION_ADDR(addr32); 81 | 82 | for (cur_stab = __STAB_BEGIN__; cur_stab != __STAB_END__; ++cur_stab) { 83 | if (is_source(cur_stab)) { 84 | /* Perform potential fixes for address */ 85 | source_addr32 = FIX_INSTRUCTION_ADDR(cur_stab->n_value); 86 | source_filename = &__STABSTR_BEGIN__[cur_stab->n_strx]; 87 | } else if (is_textline(cur_stab)) { 88 | line_addr32 = source_addr32 + cur_stab->n_value; 89 | if (line_addr32 == addr32) { 90 | found = true; 91 | if (*last < cur_stab) { 92 | info->source_file = source_filename; 93 | info->func_name = func_name; 94 | info->func_addr_lo = func_addr32; 95 | info->line_num = cur_stab->n_desc; 96 | *last = cur_stab; 97 | return 1; 98 | } 99 | } else if (found) { 100 | return 0; 101 | } 102 | } else if (is_func(cur_stab)) { 103 | func_addr32 = cur_stab->n_value; 104 | func_name = &__STABSTR_BEGIN__[cur_stab->n_strx]; 105 | } 106 | } 107 | return -1; 108 | } 109 | -------------------------------------------------------------------------------- /include/errno.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1982, 1986, 1989, 1993 3 | * The Regents of the University of California. All rights reserved. 4 | * (c) UNIX System Laboratories, Inc. 5 | * All or some portions of this file are derived from material licensed 6 | * to the University of California by American Telephone and Telegraph 7 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 | * the permission of UNIX System Laboratories, Inc. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the University nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | * 34 | * @(#)errno.h 8.5 (Berkeley) 1/21/94 35 | * 36 | * Copyright (C) 2015 Gan Quan 37 | * 38 | * This program is free software; you can redistribute it and/or modify it 39 | * under the terms of the GNU General Public License as published by the 40 | * Free Software Foundation; either version 2 of the License, or (at your 41 | * option) any later version. 42 | * 43 | */ 44 | 45 | #ifndef _ERRNO_H 46 | #define _ERRNO_H 47 | 48 | #define EPERM 1 /* Operation not permitted */ 49 | #define ENOENT 2 /* No such file or directory */ 50 | #define ESRCH 3 /* No such process */ 51 | #define EINTR 4 /* Interrupted system call */ 52 | #define EIO 5 /* Input/output error */ 53 | #define ENXIO 6 /* Device not configured */ 54 | #define E2BIG 7 /* Argument list too long */ 55 | #define ENOEXEC 8 /* Exec format error */ 56 | #define EBADF 9 /* Bad file descriptor */ 57 | #define ECHILD 10 /* No child processes */ 58 | #define EDEADLK 11 /* Resource deadlock avoided */ 59 | /* 11 was EAGAIN */ 60 | #define ENOMEM 12 /* Cannot allocate memory */ 61 | #define EACCES 13 /* Permission denied */ 62 | #define EFAULT 14 /* Bad address */ 63 | #define EBUSY 16 /* Device busy */ 64 | #define EEXIST 17 /* File exists */ 65 | #define EXDEV 18 /* Cross-device link */ 66 | #define ENODEV 19 /* Operation not supported by device */ 67 | #define ENOTDIR 20 /* Not a directory */ 68 | #define EISDIR 21 /* Is a directory */ 69 | #define EINVAL 22 /* Invalid argument */ 70 | #define ENFILE 23 /* Too many open files in system */ 71 | #define EMFILE 24 /* Too many open files */ 72 | #define ENOTTY 25 /* Inappropriate ioctl for device */ 73 | #define EFBIG 27 /* File too large */ 74 | #define ENOSPC 28 /* No space left on device */ 75 | #define ESPIPE 29 /* Illegal seek */ 76 | #define EROFS 30 /* Read-only file system */ 77 | #define EMLINK 31 /* Too many links */ 78 | #define EPIPE 32 /* Broken pipe */ 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /lib/libc/stdio/snprintf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | int snprintf(char *str, size_t size, const char *fmt, ...) 16 | { 17 | int result; 18 | va_list ap; 19 | 20 | va_start(ap, fmt); 21 | result = vsnprintf(str, size, fmt, ap); 22 | va_end(ap); 23 | 24 | return result; 25 | } 26 | 27 | #define FLAG_UNSIGNED 0x001 /* unsigned integer */ 28 | #define FLAG_ZEROPAD 0x002 /* padding with zero */ 29 | #define FLAG_NEG 0x100 /* negative integer */ 30 | 31 | int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) 32 | { 33 | #define set_ch(ch) \ 34 | do { \ 35 | str[pos++] = ch; \ 36 | if (pos == size) { \ 37 | str[size - 1] = '\0'; \ 38 | return size; \ 39 | } \ 40 | } while (0) 41 | 42 | #define is_digit(ch) (((ch) >= '0') && ((ch) <= '9')) 43 | 44 | static const char *digits = "0123456789abcdef"; 45 | 46 | long val; 47 | unsigned long uval; 48 | ssize_t width = 0; 49 | int base; 50 | int flag = 0; 51 | ssize_t pos = 0; 52 | int len; 53 | 54 | int buf_pos; 55 | char buf[25]; 56 | char *s; 57 | 58 | for ( ; *fmt != '\0'; ) { 59 | if (*fmt == '%') { 60 | ++fmt; 61 | fmt_loop: switch (*fmt) { 62 | case 'd': 63 | base = 10; 64 | val = va_arg(ap, long); 65 | if (val < 0) { 66 | flag |= FLAG_NEG; 67 | uval = -val; 68 | } else 69 | uval = val; 70 | goto print_uint; 71 | case 'o': 72 | base = 8; 73 | goto get_uint; 74 | case 'x': 75 | case 'p': 76 | base = 16; 77 | goto get_uint; 78 | case 'u': 79 | base = 10; 80 | get_uint: uval = va_arg(ap, unsigned long); 81 | print_uint: buf_pos = 0; 82 | while (uval > 0) { 83 | buf[buf_pos++] = digits[uval % base]; 84 | uval /= base; 85 | } 86 | if (buf_pos == 0) 87 | buf[buf_pos++] = '0'; 88 | if (width == 0) { 89 | if (flag & FLAG_NEG) 90 | set_ch('-'); 91 | while ((--buf_pos) >= 0) 92 | set_ch(buf[buf_pos]); 93 | } else if ((width > 0) && (flag | FLAG_ZEROPAD)) { 94 | if (flag & FLAG_NEG) 95 | set_ch('-'); 96 | while ((--width) >= 0) { 97 | if (width >= buf_pos) 98 | set_ch('0'); 99 | else 100 | set_ch(buf[width]); 101 | } 102 | } else if (width > 0) { 103 | if (flag & FLAG_NEG) 104 | buf[buf_pos++] = '-'; 105 | while ((--width) >= 0) { 106 | if (width >= buf_pos) 107 | set_ch(' '); 108 | else 109 | set_ch(buf[width]); 110 | } 111 | } 112 | ++fmt; 113 | break; 114 | case 'c': 115 | set_ch((char)va_arg(ap, int)); 116 | ++fmt; 117 | break; 118 | case 's': 119 | s = va_arg(ap, char *); 120 | if (s == NULL) 121 | s = "(null)"; 122 | for (len = 0; *s != '\0'; ++s, ++len) 123 | set_ch(*s); 124 | for (; len < width; ++len) 125 | set_ch(' '); 126 | ++fmt; 127 | break; 128 | case '%': 129 | set_ch('%'); 130 | ++fmt; 131 | break; 132 | case '0': 133 | flag |= FLAG_ZEROPAD; 134 | ++fmt; 135 | goto fmt_loop; 136 | case '1': case '2': case '3': 137 | case '4': case '5': case '6': 138 | case '7': case '8': case '9': 139 | for ( ; is_digit(*fmt); ++fmt) { 140 | width *= 10; 141 | width += (int)(*fmt) - (int)'0'; 142 | } 143 | goto fmt_loop; 144 | default: 145 | set_ch('%'); 146 | goto print_default; 147 | } 148 | flag = 0; 149 | width = 0; 150 | continue; 151 | } 152 | print_default: set_ch(*fmt); 153 | ++fmt; 154 | } 155 | set_ch('\0'); 156 | --pos; /* exclude the null byte */ 157 | #undef FLAG_UNSIGNED 158 | #undef FLAG_ZEROPAD 159 | #undef FLAG_NEG 160 | #undef is_digit 161 | #undef set_ch 162 | return pos; 163 | } 164 | 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AIMv6 2 | 3 | Reimplementation and extension of the teaching operating system xv6 on multiple platforms. 4 | 5 | Architectures (to be) included: ARM, MIPS64, i386 (the original xv6 implementation) 6 | 7 | Our first goal is to port xv6 onto ARM and MIPS64 (Loongson 2H). 8 | 9 | The guides to organize source codes can be found in each directory under FILE. 10 | 11 | Remember to add license information on top of the source code :) 12 | 13 | This repository supersedes xv6-Loongson3A, the code from which will be migrated 14 | there. 15 | 16 | Please refer to the `doc` directory for documentations. 17 | 18 | ### Toolchain 19 | Ideally, the project should be compiled by the latest GCC (or cross-GCC if 20 | cross-compiling) toolchain available on Linux distro. 21 | 22 | If prebuilt packages are not available, please use precompiled 23 | binaries and libraries provided by manufacturers. 24 | 25 | If you're a determined, patient geek, you can build your own cross-compiler 26 | from source code, as illustrated below. 27 | 28 | #### Fedora 29 | Fedora ships cross-compiler packages since release 18, and there's really no 30 | reason to keep using unsupported old versions. 31 | 32 | To install MIPS toolchain, execute (replace `dnf` with `yum` if you're running 33 | older release) 34 | ``` 35 | # dnf install gcc-mips64-linux-gnu 36 | ``` 37 | 38 | Installing ARM toolchain is similar: 39 | ``` 40 | # dnf install gcc-arm-linux-gnu 41 | ``` 42 | 43 | #### Debian (**not tested**) 44 | Cross-compilers are provided in *sid*, or *unstable* branch in Debian. 45 | 46 | Unfortunately, one should usually upgrade to *unstable* from *testing*, which, 47 | in turn, should be upgraded from *stable*. 48 | 49 | If you don't want to risk your machine being "unstable" (though not unstable as 50 | it seems - Ubuntu is based on Debian *unstable* branch), or regard the whole 51 | process as troublesome, simply jump to the **Third-party** section. 52 | 53 | Upgrading between branches is simply done by modifying `/etc/apt/sources.list` 54 | and changing sources from *testing* to *unstable*. 55 | 56 | After upgrading, the toolchains could be installed by 57 | ``` 58 | $ sudo apt-get install gcc-4.9-arm-linux-gnueabi 59 | ``` 60 | if you're playing with ARM board, or 61 | ``` 62 | $ sudo apt-get install gcc-4.9-mipsel-linux-gnu 63 | ``` 64 | if you're hacking a Loongson box. 65 | 66 | Replace 4.9 with 5 if you want to try GCC 5. 67 | 68 | #### Ubuntu (**not tested**) 69 | Awkwardly, Ubuntu ships `gcc-4.9-arm-linux-gnueabi`, but does not ship the 70 | MIPS equivalent. 71 | 72 | For ARM developers, running 73 | ``` 74 | $ sudo apt-get install gcc-arm-linux-gnueabi 75 | ``` 76 | would do everything. 77 | 78 | Obtaining MIPS toolchain is somewhat more complicated. First, you need to install 79 | `gdebi`: 80 | ``` 81 | $ sudo apt-get install gdebi 82 | ``` 83 | Download and install by `gdebi` the following `.deb` packages from Debian *sid* 84 | repository, in the order given: 85 | [binutils-mipsel-linux-gnu](https://packages.debian.org/sid/binutils-mipsel-linux-gnu) 86 | [cpp-4.9-mipsel-linux-gnu](https://packages.debian.org/sid/cpp-4.9-mipsel-linux-gnu) 87 | [gcc-4.9-mipsel-linux-gnu](https://packages.debian.org/sid/gcc-4.9-mipsel-linux-gnu) 88 | 89 | #### Third-party 90 | Loongson provided the compiler suite for building kernel [here](http://www.loongnix.org/dev/ftp/toolchain/gcc/release/CROSS_COMPILE/loongson3-gcc4.4.tar.gz) 91 | However, Loongson only supports GCC 4.4.0, which is quite obsolete compared to 92 | the now-popular version 4.9.x or 5.x.x. 93 | 94 | Another good choice is Sourcery Codebench from Mentor Graphics. The MIPS 95 | toolchain archive could be downloaded 96 | [here](sourcery.mentor.com/public/gnu_toolchain/mips-linux-gnu/mips-2015.05-18-mips-linux-gnu-i686-pc-linux-gnu.tar.bz2). 97 | 98 | `$PATH` (and `$LD_LIBRARY_PATH` for Loongson's compiler) should be modified 99 | accordingly to contain the binaries and libraries provided. 100 | Read `/etc/profile` and put the paths into appropriate files and/or locations. 101 | 102 | (TODO: add third-party ARM cross-compiler providers) 103 | 104 | #### Build from source 105 | 106 | (TODO: write source build instructions for ARM/IA32/MIPS) 107 | -------------------------------------------------------------------------------- /include/arch/armv7a-le/asm/irq.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _ASM_IRQ_H 12 | #define _ASM_IRQ_H 13 | 14 | /* 15 | * PLEASE READ ME! I AM SERIOUS! 16 | * 17 | * There are 2 methods to interrupt an ARMv7A core from the outside world. 18 | * IRQ and FIQ. Their control contains 3 parts. See Cortex-A9 MPCore TRM and 19 | * ARM GIC Architecture specs before you go on. 20 | * 21 | * The core itself, through functions {irq,fiq,interrupt}_{en,dis}able() 22 | * They control CAN I BE INTERRUPTED BY ANY IRQ/FIQ 23 | * 24 | * The interrupt distributor, through functions TODO 25 | * They control HOW TO DEAL WITH INTERRUPT REQUESTS 26 | * An ARM processor must only have 1 distributor. 27 | * 28 | * The CPU Interface, through functions TODO 29 | * They control WHAT INTERRUPT REQUEST DO I WANT TO SEE and performs actions 30 | * like ACKNOWLEDGE and END_OF_INTERRUPT 31 | */ 32 | 33 | #include 34 | #include 35 | 36 | /* 37 | * You won't want to use ICC and ICD outside the kernel, in places like MBR or 38 | * preload. 39 | */ 40 | 41 | #define ICC_PHYSBASE (MPCORE_PHYSBASE + 0x0100) 42 | #define ICD_PHYSBASE (MPCORE_PHYSBASE + 0x1000) 43 | 44 | /* FIXME is it good using macros here? */ 45 | #define icc_base (mpcore_base + 0x0100) 46 | #define icd_base (mpcore_base + 0x1000) 47 | 48 | /* ICC register offset */ 49 | #define ICC_ICR_OFFSET 0x00 50 | #define ICC_PMR_OFFSET 0x04 51 | #define ICC_BPR_OFFSET 0x08 52 | #define ICC_IAR_OFFSET 0x0C 53 | #define ICC_EOIR_OFFSET 0x10 54 | #define ICC_RPR_OFFSET 0x14 55 | #define ICC_HPIR_OFFSET 0x18 56 | #define ICC_ABPR_OFFSET 0x1C 57 | #define ICC_IDR_OFFSET 0x20 58 | 59 | /* ICD register offset */ 60 | #define ICD_DCR_OFFSET 0x000 61 | #define ICD_ICTR_OFFSET 0x004 62 | #define ICD_IIDR_OFFSET 0x008 63 | #define ICD_ISR_OFFSET 0x080 /* 32 * u32 regs */ 64 | #define ICD_ISER_OFFSET 0x100 /* 32 * u32 regs */ 65 | #define ICD_ICER_OFFSET 0x180 /* 32 * u32 regs */ 66 | #define ICD_ISPR_OFFSET 0x200 /* 32 * u32 regs */ 67 | #define ICD_ICPR_OFFSET 0x280 /* 32 * u32 regs */ 68 | #define ICD_ABR_OFFSET 0x300 /* 32 * u32 regs */ 69 | #define ICD_IPR_OFFSET 0x400 /* 255 * u32 regs */ 70 | #define ICD_IPTR_OFFSET 0x800 /* 255 * u32 regs */ 71 | #define ICD_ICFR_OFFSET 0xC00 /* 64 * u32 regs */ 72 | #define ICD_SGIR_OFFSET 0xF00 73 | 74 | static inline void icc_enable() 75 | { 76 | out32(icc_base + ICC_ICR_OFFSET, 0x1); 77 | } 78 | 79 | static inline void icc_disable() 80 | { 81 | out32(icc_base + ICC_ICR_OFFSET, 0x0); 82 | } 83 | 84 | static inline void icd_enable() 85 | { 86 | out32(icd_base + ICD_IDR_OFFSET, 0x1); 87 | } 88 | 89 | static inline void icd_disable() 90 | { 91 | out32(icd_base + ICD_IDR_OFFSET, 0x0); 92 | } 93 | 94 | static inline void irq_enable() 95 | { 96 | asm ( 97 | "mrs r0, cpsr\n\t" 98 | "bic r0, r0, #0x80\n\t" 99 | "msr cpsr, r0\n\t" 100 | ::: "r0" 101 | ); 102 | } 103 | 104 | static inline void irq_disable() 105 | { 106 | asm ( 107 | "mrs r0, cpsr\n\t" 108 | "orr r0, r0, #0x80\n\t" 109 | "msr cpsr, r0\n\t" 110 | ::: "r0" 111 | ); 112 | } 113 | 114 | static inline void fiq_enable() 115 | { 116 | asm ( 117 | "mrs r0, cpsr\n\t" 118 | "bic r0, r0, #0x40\n\t" 119 | "msr cpsr, r0\n\t" 120 | ::: "r0" 121 | ); 122 | } 123 | 124 | static inline void fiq_disable() 125 | { 126 | asm ( 127 | "mrs r0, cpsr\n\t" 128 | "orr r0, r0, #0x40\n\t" 129 | "msr cpsr, r0\n\t" 130 | ::: "r0" 131 | ); 132 | } 133 | 134 | static inline void interrupt_enable() 135 | { 136 | asm ( 137 | "mrs r0, cpsr\n\t" 138 | "bic r0, r0, #0xC0\n\t" 139 | "msr cpsr, r0\n\t" 140 | ::: "r0" 141 | ); 142 | } 143 | 144 | static inline void interrupt_disable() 145 | { 146 | asm ( 147 | "mrs r0, cpsr\n\t" 148 | "orr r0, r0, #0xC0\n\t" 149 | "msr cpsr, r0\n\t" 150 | ::: "r0" 151 | ); 152 | } 153 | 154 | #endif /* _ASM_IRQ_H */ 155 | 156 | -------------------------------------------------------------------------------- /doc/labs/lab0-prerequisites.markdown: -------------------------------------------------------------------------------- 1 | # Lab 0: Prerequisites 2 | 3 | Designing an operating system certainly involves an *awful* amount of work. 4 | 5 | Before you take this experiments, you must prepare for: 6 | 7 | 1. Reading a LOT of documentations, specifications, technical manuals, and 8 | anything else you can or can't imagine. Some of them are detailed and 9 | self-evident, while others are poorly-written. We will provide as much 10 | resource as we can. 11 | 2. Reading and struggling to understand a LOT of code. We are 12 | ~~evil~~ kind enough to provide a skeleton code for you to work with. 13 | 3. Doing a LOT of (re)searches, and asking MANY questions. 14 | 4. Doing, and *failing* a LOT of experiments. 15 | 5. (for those unluckies working on ARM/MIPS) Working WITHOUT A DEBUGGER. 16 | 17 | As a side note: teamwork absolutely helps. 18 | 19 | You may encounter mistakes, or bugs in our code or documentations as you move 20 | on. *Do not hesitate to report to us*. Reporting bugs could be in any form, 21 | from GitHub issues to emails. 22 | 23 | If you're new to Unix-like systems, you could ramp up by checking out 24 | the documentations in `unix` folder. The documentations there may provide 25 | a starting point. 26 | 27 | Take a deep breath, and get yourself ready for your very first documentation. 28 | 29 | ### Setup 30 | 31 | To do your operating system experiments you need the following: 32 | 33 | 1. A working Linux. 34 | * BSD or other Unix-like systems are OK if you can install GNU Compiler 35 | Collection (GCC). 36 | * For those who work on ARM, GNU-M4 is also needed. We'll explain later. 37 | 2. A cross-compiler suite. 38 | * Currently GNU Compiler Collection (GCC) is the only compiler suite 39 | we're supporting. Preferably, it should be the latest version, but 40 | our code supports all toolchains mentioned in the root README document. 41 | * If you insist on using other compiler suites such as 42 | CLang/LLVM, you're welcome to contribute to our repository. 43 | 3. A decent editor. 44 | * `vim(1)`, `emacs(1)`, `nano(1)`, ~~`ed(1)`~~ are all good choices. 45 | * You can use `gedit` or `kate` or IDEs on GUIs if you like. 46 | * Editors may need some configurations, try some before you start working. 47 | 4. Other tools, software and hardware. 48 | * ARM developers: make sure you have: 49 | + A working SD or SDHC card. SDXC will fallback to SDHC's behavior but is 50 | acceptable. Zedboard should have an SDHC included. 51 | + A USB cable. The ones you charge your android phone are just ok. You may 52 | need an extra cable if you want to try Vivado. 53 | * MIPS developers: make sure you have: 54 | + A serial-to-USB converter. 55 | + A SATA-to-USB converter. 56 | 57 | ### ISA and ABI 58 | 59 | *Instruction Set Architecture* includes data types, registers, 60 | instructions, addressing modes, interrupt and exception handling, and 61 | everything else one must understand for **writing programs in assemblies**. 62 | 63 | *Application Binary Interface* includes the specifications and conventions 64 | of register usage, function calls, stacks, and everything else one must 65 | understand for **writing programs in assemblies and C together**. 66 | 67 | Ramping up an ISA and an ABI involves heavy reading. Prepare yourself to 68 | read long, boring, potentially poorly-documented manuals. 69 | 70 | Here are some warmups, however: 71 | 72 | For ARM developers: 73 | * Go directly to ARM infocenter (http://infocenter.arm.com/) and you should get 74 | ALL the documents. 75 | * ARM has different ABIs and we use EABI (or GNUEABI, which is the same thing). 76 | * ARM's ISA has *A LOT OF VERSIONS* and there are optional features. Our 77 | processor core is Cortex-A9, which uses ARMv7A. 78 | * Integer division is one of the optional features, and our core does 79 | **NOT** have it implemented. 80 | 81 | For MIPS developers: 82 | * There's an excellent book named *See MIPS Run* which provides an in-depth 83 | tour to the MIPS architecture, the way MIPS assemblies interact with C 84 | programs, and the way Linux works on MIPS. To avoid copyright issues, we 85 | can't include the book in our repository, but you can probably find 86 | the electronic version online. 87 | * Or you can get a first impression in `mips64-loongson3a/prereq.markdown`. 88 | -------------------------------------------------------------------------------- /boot/arch/mips64/loongson3a/bootsect.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | 13 | #define BUFFER 0x80180000 14 | #define ELFMAGIC 0x464c457f 15 | 16 | #define PART0_ENTRY 0x1be 17 | #define PART1_ENTRY 0x1ce 18 | #define PART2_ENTRY 0x1de 19 | #define PART3_ENTRY 0x1ee 20 | 21 | #define PART_SECTOR_START 0x8 22 | #define PART_SECTOR_NUM 0xc 23 | 24 | #define SECTOR_SIZE 512 25 | 26 | typedef void (*entry_t)(); 27 | 28 | /* 29 | * Loongson 3A starts up by executing PMON in the programmable ROM. 30 | * 31 | * PMON works in 32-bit, and so does MBR. 32 | * Therefore things like "unsigned long long" should not appear in bootloader 33 | * code. 34 | * 35 | * PMON originally does not support MBR bootloader code, so I modified PMON 36 | * code to provide some help for MBR. I found that a bootloader doing all 37 | * works on its own is unrealistic for MIPS: I turned on size optimization to 38 | * save as much space as possible, skipped ELF verifications, introduced three 39 | * helper functions as well as the handle for reading the hard disk, fixed MBR 40 | * to load kernel from the second partition, skipped partition type 41 | * verification, and still nearly ran out of 446-byte space. 42 | * 43 | * The modified PMON passes four arguments to MBR: 44 | * @fd: file descriptor representing the hard disk. 45 | * @findsect: function to jump to the specified sector. 46 | * @read: read from the file descriptor, similar to read(2) 47 | * @lseek: reposition read offset, similar to lseek(2) 48 | * 49 | * The modified PMON loads MBR (this function, plus the partition entries) 50 | * to virtual address 0x80100000. 51 | */ 52 | 53 | void __attribute__((noreturn)) _boot(int fd, 54 | void (*findsect)(int, unsigned int), 55 | int (*read)(int, void *, unsigned int), 56 | int (*lseek)(int, unsigned int, int)) 57 | { 58 | int i, phnum; 59 | entry_t entry; 60 | 61 | unsigned int sector_start; 62 | unsigned int pos = 0; 63 | 64 | unsigned char *buf = (unsigned char *)BUFFER; 65 | 66 | unsigned char *part1 = ((unsigned char *)_boot) + PART1_ENTRY; 67 | 68 | /* 69 | * GCC 4.4.0 (which is the version used by Loongson Tech.) had 70 | * difficulty dereferencing unaligned address. 71 | * 72 | * In MIPS, the addresses of load/store instructions other than 73 | * LWL, LWR, SWL, SWR must be *aligned*: LH/SH operates on 74 | * addresses aligned to 2 bytes, LW/SW on 4 bytes, etc. 75 | * Since (part1 + PART_SECTOR_START) is not aligned to 4 bytes, 76 | * directly dereferencing such address throws an exception. 77 | * 78 | * The latest GCC version does not have this bug. 79 | */ 80 | 81 | /* Locate the starting sector of the second partition */ 82 | sector_start = *(unsigned short *)(part1 + PART_SECTOR_START + 2); 83 | sector_start = (sector_start << 16) + 84 | *(unsigned short *)(part1 + PART_SECTOR_START); 85 | 86 | findsect(fd, sector_start); 87 | 88 | /* Read the kernel ELF header */ 89 | read(fd, buf, sizeof(struct elf64hdr)); 90 | pos += sizeof(struct elf64hdr); 91 | 92 | struct elf64hdr *eh = (struct elf64hdr *)buf; 93 | 94 | /* Find the number of program headers (segments) */ 95 | phnum = eh->e_phnum; 96 | 97 | /* Locate the kernel entry virtual address */ 98 | entry = (entry_t)(unsigned int)(eh->e_entry); 99 | 100 | for (i = 0; i < phnum; ++i) { 101 | /* Load each loadable segment into memory */ 102 | if (read(fd, buf, sizeof(struct elf64_phdr)) == -1) 103 | /* 104 | * These breakpoints shouldn't happen and are only for 105 | * diagnostics. 106 | */ 107 | asm volatile ("break 8"); 108 | pos += sizeof(struct elf64_phdr); 109 | 110 | struct elf64_phdr *ph = (struct elf64_phdr *)buf; 111 | if (ph->p_type == PT_LOAD) { 112 | int off = (unsigned int)(ph->p_offset) - pos; 113 | if (off != 0 && lseek(fd, off, 1) == -1) 114 | asm volatile ("break 9"); 115 | if (read(fd, 116 | (unsigned char *)(unsigned int)(ph->p_vaddr), 117 | (unsigned int)(ph->p_filesz)) == -1) 118 | asm volatile ("break 10"); 119 | if (off != 0 && lseek(fd, -off, 1) == -1) 120 | asm volatile ("break 11"); 121 | } 122 | } 123 | 124 | /* Jump to entry */ 125 | (*entry)(); 126 | for (;;) 127 | /* nothing */; 128 | } 129 | -------------------------------------------------------------------------------- /Makefile.mips64: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015 Gan Quan 2 | # 3 | # This program is free software; you can redistribute it and/or modify it 4 | # under the terms of the GNU General Public License as published by the 5 | # Free Software Foundation; either version 2 of the License, or (at your 6 | # option) any later version. 7 | 8 | # Makefile for MIPS64 9 | 10 | ######## BEGIN CONFIG ######## 11 | 12 | # Cross-platform toolchain prefix. 13 | # E.g. if 14 | # CROSS_COMPILE = mips64-linux-gnu- 15 | # then the cross-compiler should be 16 | # mips64-linux-gnu-gcc 17 | # The linker should be 18 | # mips64-linux-gnu-ld 19 | # etc. 20 | CROSS_COMPILE = mips64el-n64-linux-uclibc- 21 | 22 | # Machine name. 23 | MACH = loongson3a 24 | 25 | # Target device for kernel & bootloader installation. 26 | # 27 | # IMPORTANT: 28 | # Make sure you select the correct device, or your own hard disk may become 29 | # corrupted! 30 | # I hadn't write the backup mechanism for kernel installation yet, but one 31 | # can recover MBR in case of accidents. Refer to boot/Makefile.mips64 for 32 | # more information. 33 | INSTALLDEV = /dev/sdb 34 | 35 | CCOMPILER = gcc 36 | 37 | # Only needed if the installation needs sudo privileges 38 | SUDO = sudo 39 | 40 | # The partition number. DO NOT CHANGE THIS. 41 | PARTNO = 2 42 | ######## END CONFIG ######## 43 | 44 | # Retrieve root directory. 45 | # The expression $(shell ) executes the shell command and returns 46 | # the output. 47 | ROOTDIR = $(shell pwd) 48 | 49 | # Capitalize $MACH, this is to be used for defining machine-specific 50 | # macro MACH_$(UPPERMACH). 51 | # E.g. if 52 | # MACH = loongson3a 53 | # then gcc compiles source code with 54 | # MACH_LOONGSON3A 55 | # defined. 56 | UPPERMACH = $(shell echo $(MACH) | tr a-z- A-Z_) 57 | 58 | # Cross-platform versions of GNU toolchain 59 | CC = $(CROSS_COMPILE)$(CCOMPILER) 60 | CPP = $(CROSS_COMPILE)cpp 61 | LD = $(CROSS_COMPILE)ld 62 | OBJCOPY = $(CROSS_COMPILE)objcopy 63 | OBJDUMP = $(CROSS_COMPILE)objdump 64 | 65 | # Specify all absolute include path, prepending each with -I (the include 66 | # directory flag for gcc) 67 | INCFLAG = -I. -I./include 68 | INCFLAG += -I./include/arch/$(ARCH) 69 | INCFLAG += -I./include/arch/$(ARCH)/asm/mach-$(MACH) 70 | 71 | DEFS = -DMACH_$(UPPERMACH) -DELF64 72 | 73 | # Compiling flags for GCC, see gcc(1) for details of each option. 74 | CFLAGS = -O2 -G 0 -mno-abicalls -fno-pic -Wall -mabi=64 -fno-builtin 75 | CFLAGS += -nostdinc -nostdlib -ggdb -mips64r2 -gstabs -EL -mno-mips16 76 | CFLAGS += $(INCFLAG) $(DEFS) 77 | 78 | # Linker script for ld(1) 79 | LDSCRIPT = kern/arch/$(ARCH)/ldscript.ld 80 | # Linker flag for ld(1) 81 | LDFLAGS = -EL -N 82 | 83 | # All object files 84 | OBJS = kern/arch/$(ARCH)/start.o \ 85 | kern/arch/$(ARCH)/setup.o \ 86 | kern/init/main.o \ 87 | drivers/serial/uart16550.o \ 88 | drivers/serial/uart.o \ 89 | drivers/serial/uart-printf.o \ 90 | drivers/clock/mc146818.o \ 91 | lib/libc/stdio/snprintf.o \ 92 | lib/libc/string/memset.o 93 | 94 | TEST_OBJS = 95 | 96 | # Final program 97 | BINARY = bootstrap 98 | # Disassembly 99 | DISASSEMBLY = $(BINARY).s 100 | 101 | # Export all variables above to child make processes, which will 102 | # spawn when compiling bootloader and userspace programs 103 | export 104 | 105 | # all: the default target when no target is specified in command 106 | # line. 107 | # 108 | # Makes kernel and bootloader. 109 | all: $(BINARY) boot tools 110 | 111 | # elf: Make kernel by linking the object files and disassembling 112 | # the binary program after all object files are compiled. 113 | $(BINARY): $(OBJS) $(TEST_OBJS) 114 | $(LD) $(LDFLAGS) -T $(LDSCRIPT) -o $(BINARY) $(OBJS) $(TEST_OBJS) 115 | $(OBJDUMP) -S $(BINARY) >$(DISASSEMBLY) 116 | 117 | # boot: Make bootloader. 118 | # Change into boot/ directory and build there. 119 | boot: 120 | cd boot && make -f Makefile.$(ARCH) 121 | 122 | # tools: Make tools 123 | tools: 124 | cd tools/stab && make 125 | 126 | # install: Perform kernel and bootloader installation. 127 | # 128 | # First install bootloader by changing into boot/ directory and 129 | # perform bootloader installation, then invoke the kernel installation 130 | # perl script. 131 | install: all 132 | cd boot && make -f Makefile.$(ARCH) install 133 | $(SUDO) dd if=$(BINARY) of=$(INSTALLDEV)$(PARTNO) conv=notrunc 134 | 135 | # clean: Remove all files generated by make. 136 | clean: 137 | cd boot && make -f Makefile.$(ARCH) clean 138 | cd tools/stab && make clean 139 | rm -rf $(OBJS) $(BINARY) 140 | 141 | # make by default doesn't know how to compile assemblies. So we specify 142 | # the procedure here. 143 | .S.o: 144 | $(CC) $(CFLAGS) -c $< -o $*.o 145 | 146 | .PHONY: all boot tools clean install test 147 | -------------------------------------------------------------------------------- /drivers/serial/uart-zynq7000.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _DRIVERS_SERIAL_UART_ZYNQ7000_H 12 | #define _DRIVERS_SERIAL_UART_ZYNQ7000_H 13 | 14 | /* 15 | * ZYNQ7000 UART driver 16 | */ 17 | 18 | /* 19 | * Include config.h to obtain UART base address (through 20 | * asm/mach-$MACH/config.h) 21 | */ 22 | #include 23 | 24 | #ifdef KERNEL 25 | #define UART_BASE uart1_base 26 | #else /* KERNEL */ 27 | #define UART_BASE UART1_PHYSBASE 28 | #endif /* KERNEL */ 29 | 30 | /* Register Offset */ 31 | #define UART_OFFSET_CR 0x00 32 | #define UART_OFFSET_MR 0x04 33 | #define UART_OFFSET_IER 0x08 34 | #define UART_OFFSET_IDR 0x0C 35 | #define UART_OFFSET_IMR 0x10 36 | #define UART_OFFSET_ISR 0x14 37 | #define UART_OFFSET_BAUDGEN 0x18 38 | #define UART_OFFSET_RXTOUT 0x1C 39 | #define UART_OFFSET_RXWM 0x20 40 | #define UART_OFFSET_MODEMCR 0x24 41 | #define UART_OFFSET_MODEMSR 0x28 42 | #define UART_OFFSET_SR 0x2C 43 | #define UART_OFFSET_FIFO 0x30 44 | #define UART_OFFSET_BAUDDIV 0x34 45 | #define UART_OFFSET_FLOWDEL 0x38 46 | #define UART_OFFSET_TXWM 0x44 47 | 48 | /* CR */ 49 | #define UART_CR_STOPBRK 0x0100 50 | #define UART_CR_STARTBRK 0x0080 51 | #define UART_CR_TORST 0x0040 52 | #define UART_CR_EN_DIS_MASK 0x003C 53 | #define UART_CR_TX_DIS 0x0020 54 | #define UART_CR_TX_EN 0x0010 55 | #define UART_CR_RX_DIS 0x0008 56 | #define UART_CR_RX_EN 0x0004 57 | #define UART_CR_TXRST 0x0002 58 | #define UART_CR_RXRST 0x0001 59 | 60 | /* MR */ 61 | #define UART_MR_CCLK 0x00000400 62 | #define UART_MR_CHMODE_MASK 0x00000300 63 | #define UART_MR_CHMODE_R_LOOP 0x00000300 64 | #define UART_MR_CHMODE_L_LOOP 0x00000200 65 | #define UART_MR_CHMODE_ECHO 0x00000100 66 | #define UART_MR_CHMODE_NORM 0x00000000 67 | #define UART_MR_STOPMODE_MASK 0x000000A0 68 | #define UART_MR_STOPMODE_2_BIT 0x00000080 69 | #define UART_MR_STOPMODE_1_5_BIT 0x00000040 70 | #define UART_MR_STOPMODE_1_BIT 0x00000000 71 | #define UART_MR_PARITY_MASK 0x00000038 72 | #define UART_MR_PARITY_NONE 0x00000020 73 | #define UART_MR_PARITY_MARK 0x00000018 74 | #define UART_MR_PARITY_SPACE 0x00000010 75 | #define UART_MR_PARITY_ODD 0x00000008 76 | #define UART_MR_PARITY_EVEN 0x00000000 77 | #define UART_MR_CHARLEN_6_BIT 0x00000006 78 | #define UART_MR_CHARLEN_7_BIT 0x00000004 79 | #define UART_MR_CHARLEN_8_BIT 0x00000000 80 | #define UART_MR_CHARLEN_MASK 0x00000006 81 | #define UART_MR_CLKSEL 0x00000001 82 | #define UART_MR_CHMODE_SHIFT 8 83 | #define UART_MR_STOPMODE_SHIFT 6 84 | #define UART_MR_PARITY_SHIFT 3 85 | #define UART_MR_CHARLEN_SHIFT 1 86 | 87 | /* IDR, IER, IMR, ISR */ 88 | #define UART_IXR_MASK 0x00001FFF 89 | #define UART_IXR_TOVR 0x00001000 90 | #define UART_IXR_TNFUL 0x00000800 91 | #define UART_IXR_TTRIG 0x00000400 92 | #define UART_IXR_DMS 0x00000200 93 | #define UART_IXR_TOUT 0x00000100 94 | #define UART_IXR_PARITY 0x00000080 95 | #define UART_IXR_FRAMING 0x00000040 96 | #define UART_IXR_OVER 0x00000020 97 | #define UART_IXR_TXFULL 0x00000010 98 | #define UART_IXR_TXEMPTY 0x00000008 99 | #define UART_IXR_RXFULL 0x00000004 100 | #define UART_IXR_RXEMPTY 0x00000002 101 | #define UART_IXR_RXOVR 0x00000001 102 | 103 | /* SR */ 104 | #define UART_SR_RXOVR 0x0001 105 | #define UART_SR_RXEMPTY 0x0002 106 | #define UART_SR_RXFULL 0x0004 107 | #define UART_SR_TXEMPTY 0x0008 108 | #define UART_SR_TXFULL 0x0010 109 | #define UART_SR_RACTIVE 0x0400 110 | #define UART_SR_TACTIVE 0x0800 111 | #define UART_SR_FLOWDEL 0x1000 112 | #define UART_SR_TTRIG 0x2000 113 | #define UART_SR_TNFUL 0x4000 114 | 115 | /* BAUDGEN */ 116 | #define UART_BAUDGEN_MASK 0x0000FFFF 117 | #define UART_BAUDGEN_DISABLE 0x00000000 118 | #define UART_BAUDGEN_RESET_VAL 0x0000028B 119 | 120 | /* RXTOUT */ 121 | #define UART_RXTOUT_DISABLE 0x00000000 122 | #define UART_RXTOUT_MASK 0x000000FF 123 | 124 | /* RXWM */ 125 | #define UART_RXWM_MASK 0x0000003F 126 | #define UART_RXWM_RESET_VAL 0x00000020 127 | #define UART_RXWM_DISABLE 0x00000000 128 | 129 | /* MODEMCR */ 130 | #define UART_MODEMCR_FCM 0x00000010 131 | #define UART_MODEMCR_RTS 0x00000002 132 | #define UART_MODEMCR_DTR 0x00000001 133 | 134 | /* MODEMSR */ 135 | #define UART_MODEMSR_FCMS 0x00000100 136 | #define UART_MODEMSR_DCD 0x00000080 137 | #define UART_MODEMSR_RI 0x00000040 138 | #define UART_MODEMSR_DSR 0x00000020 139 | #define UART_MODEMSR_CTS 0x00000010 140 | #define UART_MODEMSR_DDCD 0x00000008 141 | #define UART_MODEMSR_TERI 0x00000004 142 | #define UART_MODEMSR_DDSR 0x00000002 143 | #define UART_MODEMSR_DCTS 0x00000001 144 | 145 | /* BAUDDIV */ 146 | #define UART_BAUDDIV_MASK 0x000000FF 147 | #define UART_BAUDDIV_RESET_VAL 0x0000000F 148 | 149 | /* FLOWDEL */ 150 | #define UART_FLOWDEL_MASK 0x0000003F 151 | 152 | /* TXWM */ 153 | #define UART_TXWM_MASK 0x0000003F 154 | #define UART_TXWM_RESET_VAL 0x00000020 155 | 156 | void uart_init(void); 157 | void uart_enable(void); 158 | void uart_disable(void); 159 | unsigned char uart_spin_getbyte(void); 160 | void uart_spin_putbyte(unsigned char byte); 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /drivers/misc/dtb-zynq7000.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _DTB_H 12 | #define _DTB_H 13 | 14 | #include 15 | 16 | /* PHYSICAL BASE ADDRESS AS MACROS */ 17 | /* See Zynq7000 APSoC TRM (Xilinx UG585) for details. */ 18 | #define OCM_PHYSBASE_LO 0x00000000 /* size=256K */ 19 | #define DDR_PHYSBASE_SCU 0x00000000 20 | #define DDR_PHYSBASE_NOSCU 0x00100000 21 | #define AXI_GP0_PHYSBASE 0x40000000 /* size=1G */ 22 | #define AXI_GP1_PHYSBASE 0x80000000 /* size=1G */ 23 | 24 | /* FIXME DDR_PHYSEND is from Zedboard and not Zynq7000 */ 25 | #define DDR_PHYSEND 0x20000000 /* 512M */ 26 | 27 | #define UART0_PHYSBASE 0xE0000000 28 | #define UART1_PHYSBASE 0xE0001000 29 | #define USB0_PHYSBASE 0xE0002000 30 | #define USB1_PHYSBASE 0xE0003000 31 | #define I2C0_PHYSBASE 0xE0004000 32 | #define I2C1_PHYSBASE 0xE0005000 33 | #define SPI0_PHYSBASE 0xE0006000 34 | #define SPI1_PHYSBASE 0xE0007000 35 | #define CAN0_PHYSBASE 0xE0008000 36 | #define CAN1_PHYSBASE 0xE0009000 37 | #define GPIO_PHYSBASE 0xE000A000 38 | #define GEM0_PHYSBASE 0xE000B000 39 | #define GEM1_PHYSBASE 0xE000C000 40 | #define QSPI_PHYSBASE 0xE000D000 41 | #define SMCC_PHYSBASE 0xE000E000 42 | 43 | #define SD0_PHYSBASE 0xE0100000 44 | #define SD1_PHYSBASE 0xE0101000 45 | 46 | #define SMC_NAND_PHYSBASE 0xE1000000 47 | #define SMC_SRAM0_PHYSBASE 0xE2000000 48 | #define SMC_SRAM1_PHYSBASE 0xE4000000 49 | 50 | #define SLCR_PHYSBASE 0xF8000000 51 | #define TTC0_PHYSBASE 0xF8001000 52 | #define TTC1_PHYSBASE 0xF8002000 53 | #define DMAC0_S_PHYSBASE 0xF8003000 54 | #define DMAC0_NS_PHYSBASE 0xF8004000 55 | #define SWDT_PHYSBASE 0xF8005000 56 | #define DDRC_PHYSBASE 0xF8006000 57 | #define DEVCFG_PHYSBASE 0xF8007000 58 | #define AXI_HP0_PHYSBASE 0xF8008000 59 | #define AXI_HP1_PHYSBASE 0xF8009000 60 | #define AXI_HP2_PHYSBASE 0xF800A000 61 | #define AXI_HP3_PHYSBASE 0xF800B000 62 | #define OCMC_PHYSBASE 0xF800C000 63 | 64 | #define DEBUG_DAP_ROM_PHYSBASE 0xF8800000 65 | #define DEBUG_ETB_PHYSBASE 0xF8801000 66 | #define DEBUG_CTI_ETB_TPIU_PHYSBASE 0xF8802000 67 | #define DEBUG_TPIU_PHYSBASE 0xF8803000 68 | #define DEBUG_FUNNEL_PHYSBASE 0xF8804000 69 | #define DEBUG_ITM_PHYSBASE 0xF8805000 70 | #define DEBUG_CTI_FTM_PHYSBASE 0xF8809000 71 | #define DEBUG_FTM_PHYSBASE 0xF880B000 72 | 73 | #define DEBUG_CPU_PMU0_PHYSBASE 0xF8891000 74 | #define DEBUG_CPU_PMU1_PHYSBASE 0xF8893000 75 | #define DEBUG_CPU_CTI0_PHYSBASE 0xF8898000 76 | #define DEBUG_CPU_CTI1_PHYSBASE 0xF8899000 77 | #define DEBUG_CPU_PTM0_PHYSBASE 0xF889C000 78 | #define DEBUG_CPU_PTM1_PHYSBASE 0xF889D000 79 | 80 | #define GPV_TRUSTZONE_PHYSBASE 0xF8900000 81 | #define GPV_QOS301_CPU_PHYSBASE 0xF8946000 82 | #define GPV_QOS301_DMAC_PHYSBASE 0xF8947000 83 | #define GPV_QOS301_IOU_PHYSBASE 0xF8948000 84 | 85 | #define MPCORE_PHYSBASE 0xF8F00000 /* size=8K */ 86 | #define L2CACHE_PHYSBASE 0xF8F02000 87 | 88 | #define QSPI_LINEAR_PHYSBASE 0xFC000000 89 | #define OCM_PHYSBASE_HI 0xFFFC0000 /* size=256K */ 90 | 91 | #ifdef KERNEL 92 | #ifndef _DTB_C 93 | 94 | extern u32 ocm_base; 95 | extern u32 ddr_base; 96 | extern u32 axi_gp0_base; 97 | extern u32 axi_gp1_base; 98 | extern u32 qspi_linear_base; 99 | 100 | extern u32 ddr_end; 101 | 102 | extern u32 uart0_base; 103 | extern u32 uart1_base; 104 | extern u32 usb0_base; 105 | extern u32 usb1_base; 106 | extern u32 i2c0_base; 107 | extern u32 i2c1_base; 108 | extern u32 spi0_base; 109 | extern u32 spi1_base; 110 | extern u32 can0_base; 111 | extern u32 can1_base; 112 | extern u32 gpio_base; 113 | extern u32 gem0_base; 114 | extern u32 gem1_base; 115 | extern u32 qspi_base; 116 | extern u32 smcc_base; 117 | 118 | extern u32 sd0_base; 119 | extern u32 sd1_base; 120 | 121 | extern u32 smc_nand_base; 122 | extern u32 smc_sram0_base; 123 | extern u32 smc_sram1_base; 124 | 125 | extern u32 slcr_base; 126 | extern u32 ttc0_base; 127 | extern u32 ttc1_base; 128 | extern u32 dmac0_s_base; 129 | extern u32 dmac0_ns_base; 130 | extern u32 swdt_base; 131 | extern u32 ddrc_base; 132 | extern u32 devcfg_base; 133 | extern u32 axi_hp0_base; 134 | extern u32 axi_hp1_base; 135 | extern u32 axi_hp2_base; 136 | extern u32 axi_hp3_base; 137 | extern u32 ocmc_base; 138 | 139 | extern u32 debug_dap_rom_base; 140 | extern u32 debug_etb_base; 141 | extern u32 debug_cti_etb_tpiu_base; 142 | extern u32 debug_tpiu_base; 143 | extern u32 debug_funnel_base; 144 | extern u32 debug_itm_base; 145 | extern u32 debug_cti_ftm_base; 146 | extern u32 debug_ftm_base; 147 | 148 | extern u32 debug_cpu_pmu0_base; 149 | extern u32 debug_cpu_pmu1_base; 150 | extern u32 debug_cpu_cti0_base; 151 | extern u32 debug_cpu_cti1_base; 152 | extern u32 debug_cpu_ptm0_base; 153 | extern u32 debug_cpu_ptm1_base; 154 | 155 | extern u32 gpv_trustzone_base; 156 | extern u32 gpv_qos301_cpu_base; 157 | extern u32 gpv_qos301_dmac_base; 158 | extern u32 gpv_qos301_iou_base; 159 | 160 | extern u32 mpcore_base; 161 | extern u32 l2cache_base; 162 | 163 | #endif /* _DTB_C */ 164 | #endif /* KERNEL */ 165 | 166 | #endif /* _DTB_H */ 167 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/addrspace.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is subject to the terms and conditions of the GNU General Public 3 | * License. See the file "COPYING" in the main directory of this archive 4 | * for more details. 5 | * 6 | * Copyright (C) 2015 Gan Quan 7 | */ 8 | 9 | #ifndef _ASM_ADDRSPACE_H 10 | #define _ASM_ADDRSPACE_H 11 | 12 | /* 13 | * Virtual Address Space definitions 14 | * 15 | * On MIPS64 architectures, virtual addresses are 64-bit: 16 | * 17 | * 6666555555555544444444443333333333222222222211111111110000000000 18 | * 3210987654321098765432109876543210987654321098765432109876543210 19 | * ---------------------------------------------------------------- 20 | * 3333333333333333222222222222222211111111111111110000000000000000 21 | * fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210 22 | * 23 | * The 63rd and 62nd bit matches current KSU mode. 24 | */ 25 | 26 | /* 27 | * Meaning of Mapped section: 28 | * Virtual addresses in Mapped section are first extended by ASID 29 | * in CP0 EntryHi register. The VPN part are then extracted and 30 | * compared with TLB. If VPN matches an entry in TLB, the global 31 | * bit and ASID field are checked in order to determine whether 32 | * a TLB hit or a TLB miss occur. 33 | */ 34 | 35 | /* 36 | * User address space 37 | * All access to virtual memory address outside XUSEG causes an 38 | * address error. 39 | */ 40 | 41 | /* Mapped */ 42 | #define XUSEG_BEGIN 0x0000000000000000 43 | #define XUSEG_END 0x0000ffffffffffff 44 | 45 | #define XUSEG XUSEG_BEGIN 46 | 47 | /* 48 | * Supervisor address space 49 | * All access to virtual memory address outside XSUSEG and XSSEG 50 | * causes an address error. 51 | */ 52 | 53 | /* 54 | * User address space is available in supervisor mode. 55 | */ 56 | 57 | /* Mapped */ 58 | #define XSUSEG_BEGIN XUSEG_BEGIN 59 | #define XSUSEG_END XUSEG_END 60 | #define XSSEG_BEGIN 0x4000000000000000 61 | #define XSSEG_END 0x4000ffffffffffff 62 | #define CSSEG_BEGIN 0xffffffffc0000000 /* compat */ 63 | #define CSSEG_END 0xffffffffdfffffff /* compat */ 64 | 65 | #define XSUSEG XSUSEG_BEGIN 66 | #define XSSEG XSSEG_BEGIN 67 | #define CSSEG CSSEG_BEGIN 68 | 69 | /* 70 | * Kernel address space, more complicated 71 | */ 72 | 73 | /* 74 | * User and supervisor address space are available in kernel mode. 75 | */ 76 | 77 | /* Mapped */ 78 | #define XKUSEG_BEGIN XUSEG_BEGIN 79 | #define XKUSEG_END XUSEG_END 80 | #define XKSSEG_BEGIN XSSEG_BEGIN 81 | #define XKSSEG_END XSSEG_END 82 | 83 | /* 84 | * Physical address space are unmapped. 85 | * Low 48 bits are directly taken as physical address. 86 | * 61st to 59th bit determine cache coherency. 87 | */ 88 | 89 | /* Unmapped */ 90 | #define XKPHY_BEGIN 0x8000000000000000 91 | #define XKPHY_END 0xbfffffffffffffff 92 | 93 | /* Mapped */ 94 | #define XKSEG_BEGIN 0xc000000000000000 95 | #define XKSEG_END 0xc00000ff7fffffff 96 | 97 | /* 98 | * Finally some MIPS32 compatible kernel sections 99 | */ 100 | 101 | /* 102 | * CKSEG0 is mapped to the lowest 256 MB physical memory directly 103 | * by simply stripping off the higher bits (or by subtracting 104 | * 0xffffffff80000000). Memory there are typically cached. 105 | * 106 | * Addresses greater than 0xffffffff90000000 correspond to I/O. 107 | * 108 | * It's assumed here that BIOS had already properly initialized 109 | * caches and TLB. 110 | */ 111 | 112 | /* Unmapped, cached */ 113 | #define CKSEG0_BEGIN 0xffffffff80000000 /* compat */ 114 | #define CKSEG0_END 0xffffffff9fffffff /* compat */ 115 | 116 | /* 117 | * CKSEG1 is also mapped to the lowest 256MB physical memory. 118 | * The only difference is that accessing this address space 119 | * does not go through caches. 120 | * 121 | * In most cases, this address is used for I/O and BIOS ROM. 122 | * 123 | * Loongson 3A user manual suggests that lower 256MB-512MB 124 | * should be reserved for I/O. In terms of virtual address, 125 | * address region 0xffffffffb0000000-0xffffffffbfffffff 126 | * (or 0x9000000010000000-0x900000001fffffff in extended addressing) 127 | * should be reserved. 128 | */ 129 | 130 | /* Unmapped, uncached */ 131 | #define CKSEG1_BEGIN 0xffffffffa0000000 /* compat */ 132 | #define CKSEG1_END 0xffffffffbfffffff /* compat */ 133 | 134 | /* Mapped */ 135 | #define CKSSEG_BEGIN 0xffffffffc0000000 /* compat, supervisor */ 136 | #define CKSSEG_END 0xffffffffdfffffff /* compat, supervisor */ 137 | #define CKSEG3_BEGIN 0xffffffffe0000000 /* compat */ 138 | #define CKSEG3_END 0xffffffffffffffff /* compat */ 139 | 140 | #define XKUSEG XKUSEG_BEGIN 141 | #define XKSSEG XKSSEG_BEGIN 142 | #define XKPHY XKPHY_BEGIN 143 | #define XKSEG XKSEG_BEGIN 144 | #define CKSEG0 CKSEG0_BEGIN 145 | #define CKSEG1 CKSEG1_BEGIN 146 | #define CKSSEG CKSSEG_BEGIN 147 | #define CKSEG3 CKSEG3_BEGIN 148 | 149 | #define IO_BASE_CACHED (XKPHY + 0x1800000000000000) 150 | #define IO_BASE (XKPHY + 0x1000000000000000) 151 | #define KERNBASE IO_BASE_CACHED 152 | 153 | /* 154 | * Old 32-bit section namings 155 | */ 156 | 157 | #define USEG XUSEG 158 | #define SSEG CSSEG 159 | #define KSEG0 CKSEG0 160 | #define KSEG1 CKSEG1 161 | #define KSSEG CKSSEG 162 | #define KSEG3 CKSEG3 163 | 164 | /* Exception handler entry address */ 165 | #define EXCEPT_BASE 0xffffffff80000000 /* Base address */ 166 | #define EXCEPT_TLB EXCEPT_BASE /* TLB refill handler */ 167 | #define EXCEPT_TLBX (EXCEPT_BASE + 0x80) /* TLB refill handler 64 bit */ 168 | #define EXCEPT_CACHEERR (EXCEPT_BASE + 0x100) /* Cache error handler */ 169 | #define EXCEPT_GENERIC (EXCEPT_BASE + 0x180) /* Generic handler */ 170 | 171 | #endif 172 | -------------------------------------------------------------------------------- /drivers/serial/uart16550.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 MontaVista Software Inc. 3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 | * Copyright (C) 2015 Gan Quan 5 | * 6 | * This program is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; either version 2 of the License, or (at your 9 | * option) any later version. 10 | * 11 | */ 12 | 13 | #ifndef _DRIVERS_SERIAL_UART16550_H 14 | #define _DRIVERS_SERIAL_UART16550_H 15 | 16 | /* 17 | * UART 16550A driver 18 | * 19 | * References: 20 | * https://www.freebsd.org/doc/en_US.ISO8859-1/articles/serial-uart/ 21 | * http://ecee.colorado.edu/~ecen2120/Manual/uart/UART.html 22 | */ 23 | 24 | /* 25 | * Include config.h to obtain UART base address (through 26 | * asm/mach-$MACH/config.h) 27 | */ 28 | #include 29 | 30 | #define UART16550_BAUD_2400 2400 31 | #define UART16550_BAUD_4800 4800 32 | #define UART16550_BAUD_9600 9600 33 | #define UART16550_BAUD_19200 19200 34 | #define UART16550_BAUD_38400 38400 35 | #define UART16550_BAUD_57600 57600 36 | #define UART16550_BAUD_115200 115200 37 | 38 | #ifndef UART16550_REG_OFFSET 39 | #define UART16550_REG_OFFSET 1 40 | #endif 41 | 42 | /* 43 | * TODO: verify if this register specification, as given in Loongson 2H 44 | * manual, is compatible to others. 45 | */ 46 | #define UART_RCV_BUFFER 0 /* R/O */ 47 | #define UART_TRANS_HOLD 0 /* W/O */ 48 | #define UART_INTR_ENABLE 1 49 | #define UART_INTR_ID 2 /* R/O */ 50 | #define UART_FIFO_CONTROL 2 /* W/O */ 51 | #define UART_LINE_CONTROL 3 52 | #define UART_MODEM_CONTROL 4 /* W/O? */ 53 | #define UART_LINE_STATUS 5 /* R/O */ 54 | #define UART_MODEM_STATUS 6 /* R/O */ 55 | 56 | #define UART_DIVISOR_LSB 0 /* DLAB = 1 */ 57 | #define UART_DIVISOR_MSB 1 /* DLAB = 1 */ 58 | 59 | /* Interrupt Enable Register contents */ 60 | #define UART_IER_DSSI 0x08 /* Modem Status Interrupt */ 61 | #define UART_IER_LSI 0x04 /* Line Status Interrupt */ 62 | #define UART_IER_THREI 0x02 /* Transmitter Holding Register Empty */ 63 | #define UART_IER_RBFI 0x01 /* Receive Buffer Available */ 64 | 65 | /* Interrupt Identifier Register contents */ 66 | #define UART_IIR_IMASK 0x0e /* AND this to get interrupt type */ 67 | # define UART_IIR_RECVERR 0x06 /* Receive Error */ 68 | # define UART_IIR_RBF 0x04 /* Data Available */ 69 | # define UART_IIR_STALE 0x0c /* Stale Data */ 70 | # define UART_IIR_TBE 0x02 /* Transmit Buffer has more room */ 71 | # define UART_IIR_DSS 0x00 /* Modem Status Change */ 72 | #define UART_IIR_nIP 0x01 /* Interrupt Pending (negative) */ 73 | 74 | /* FIFO Control Register contents */ 75 | #define UART_FCR_RTB_1 0x00 /* Trigger when received 1 byte */ 76 | #define UART_FCR_RTB_4 0x40 /* ... 4 bytes */ 77 | #define UART_FCR_RTB_8 0x80 /* ... 8 bytes */ 78 | #define UART_FCR_RTB_14 0xc0 /* ... 14 bytes */ 79 | #define UART_FCR_RST_TRANSMIT 0x04 /* Reset Transmit FIFO */ 80 | #define UART_FCR_RST_RECEIVER 0x02 /* Reset Receiver FIFO*/ 81 | #define UART_FCR_ENABLE 0x01 /* Enable FIFO */ 82 | 83 | /* Line Control Register Masks */ 84 | 85 | /* Divisor Latch Access Bit */ 86 | #define UART_LCR_DLAB 0x80 87 | 88 | /* Break Control Bit */ 89 | #define UART_LCR_BREAK 0x40 90 | 91 | /* Parity selection */ 92 | #define UART_LCR_PARITY_NONE 0x00 93 | #define UART_LCR_PARITY_ODD 0x08 94 | #define UART_LCR_PARITY_EVEN 0x18 95 | #define UART_LCR_PARITY_MARK 0x28 96 | #define UART_LCR_PARITY_SPACE 0x38 97 | 98 | /* Data length */ 99 | #define UART_LCR_DATA_5BIT 0x0 100 | #define UART_LCR_DATA_6BIT 0x1 101 | #define UART_LCR_DATA_7BIT 0x2 102 | #define UART_LCR_DATA_8BIT 0x3 103 | 104 | /* Stop bit selection */ 105 | #define UART_LCR_STOP_1BIT 0x0 106 | #define UART_LCR_STOP_2BIT 0x4 107 | 108 | /* Modem Control Register contents */ 109 | #define UART_MCR_LOOPBACK_CTL 0x10 /* Loopback control */ 110 | #define UART_MCR_OUT2 0x08 /* OUT 2 signal, for interrupts */ 111 | #define UART_MCR_OUT1 0x04 /* OUT 1 signal */ 112 | #define UART_MCR_RTSC 0x02 /* Request-To-Send control */ 113 | #define UART_MCR_DTRC 0x01 /* Data-Terminal-Ready control */ 114 | 115 | /* Line Status Register contents */ 116 | #define UART_LSR_ERROR 0x80 /* Error occurred */ 117 | #define UART_LSR_TEMT 0x40 /* Transmitter Empty */ 118 | #define UART_LSR_THRE 0x20 /* Transmitter Holding Register Empty */ 119 | #define UART_LSR_BREAK_INTR 0x10 /* Break Interrupt */ 120 | #define UART_LSR_FRAME_ERROR 0x08 /* self-descriptive */ 121 | #define UART_LSR_PARITY_ERROR 0x04 /* ditto */ 122 | #define UART_LSR_OVERRUN_ERROR 0x02 /* ditto */ 123 | #define UART_LSR_DATA_READY 0x01 /* ditto */ 124 | 125 | /* Modem Status Register contents, we don't care mostly */ 126 | 127 | /* 128 | * The following four bits are marked complement in Loongson 2H manual, somehow 129 | * contradicts the description in the references. 130 | */ 131 | #define UART_MSR_DCD 0x80 /* Data Carrier Detect */ 132 | #define UART_MSR_RI 0x40 /* Ring Indicator */ 133 | #define UART_MSR_DSR 0x20 /* Data Set Ready */ 134 | #define UART_MSR_CTS 0x10 /* Clear To Send */ 135 | /* Deltas */ 136 | #define UART_MSR_DDCD 0x08 137 | #define UART_MSR_TERI 0x04 /* RI low-to-high transition */ 138 | #define UART_MSR_DDSR 0x02 139 | #define UART_MSR_DCTS 0x01 140 | 141 | #ifndef __ASSEMBLER__ 142 | 143 | #include 144 | #include 145 | 146 | /* 147 | * TODO: implement in8() and out8() somewhere. 148 | * i386 CPUs access UART via in and out instructions, while MIPS do so 149 | * by reading and writing memory-mapped registers. 150 | */ 151 | #define UART_READ(reg) in8(UART_BASE + (reg)) 152 | #define UART_WRITE(reg, data) out8(UART_BASE + (reg), data) 153 | 154 | void uart_init(void); 155 | void uart_enable(void); 156 | void uart_disable(void); 157 | unsigned char uart_spin_getbyte(void); 158 | void uart_spin_putbyte(unsigned char byte); 159 | 160 | #endif 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * asmmacro.h: Assembler macros to make things easier to read. 3 | * 4 | * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 5 | * Copyright (C) 1998 Ralf Baechle 6 | * Copyright (C) 2015 Gan Quan 7 | */ 8 | 9 | #ifndef _ASM_ASM_H 10 | #define _ASM_ASM_H 11 | 12 | #include 13 | #include 14 | 15 | /* 16 | * LEAF - declare leaf routine 17 | */ 18 | #define LEAF(symbol) \ 19 | .globl symbol; \ 20 | .align 2; \ 21 | .type symbol, @function; \ 22 | .ent symbol,0; \ 23 | symbol: .frame sp,0,ra 24 | 25 | /* 26 | * NESTED - declare nested routine entry point 27 | */ 28 | #define NESTED(symbol, framesize, rpc) \ 29 | .globl symbol; \ 30 | .align 2; \ 31 | .type symbol, @function; \ 32 | .ent symbol,0; \ 33 | symbol: .frame sp, framesize, rpc 34 | 35 | 36 | /* 37 | * END - mark end of function 38 | */ 39 | #define END(function) \ 40 | .end function; \ 41 | .size function,.-function 42 | 43 | /* 44 | * GCC supported pseudo-instructions which are commonly used for convenience: 45 | * 46 | * Mnemonic Parameters Description 47 | * -------------------------------------------------------------------------- 48 | * BLT r1, r2, label Branch to label if r1 < r2 49 | * BGT r1, r2, label Branch to label if r1 > r2 50 | * BLE r1, r2, label Branch to label if r1 <= r2 51 | * BGE r1, r2, label Branch to label if r1 >= r2 52 | * NOT rd, rs rd = ~rs 53 | * NEG rd, rs rd = -rs 54 | * LI rd, imm rd = imm 55 | * LA rd, off(rs) rd = off + rs 56 | * MOVE rd, rs rd = rs 57 | * SLE rd, rs, rt rd = (rs <= rt) ? 1 : 0 58 | * SGE rd, rs, rt rd = (rs >= rt) ? 1 : 0 59 | * SGT rd, rs, rt rd = (rs > rt) ? 1 : 0 60 | * 61 | * These instructions do not exist in MIPS instruction set, and would be 62 | * translated to equivalent instruction combinations. 63 | * 64 | * Moreover, arithmetic/logical operations could have only two operands 65 | * instead of the standard three in GCC. In this case, the ALU receives 66 | * both operands, compute the result, and store it back to the destination 67 | * register: 68 | * ADD rd, rs rd += rs 69 | */ 70 | 71 | /* 72 | * DEFINE_ - Define a local for current assembly source only 73 | * DEFINE_GLOBAL_ - Define a global shared across assembly files 74 | */ 75 | #define DEFINE_STRING(sym, str) \ 76 | .type sym, @object; \ 77 | .align 2; \ 78 | sym: .ascii str; \ 79 | .size sym,.-sym; 80 | 81 | #define DEFINE_GLOBAL_STRING(sym, str) \ 82 | .globl sym; \ 83 | .type sym, @common; \ 84 | .align 2; \ 85 | sym: .ascii str; \ 86 | .size sym,.-sym; 87 | 88 | #endif 89 | 90 | #define DEFINE_WORD(sym, word) \ 91 | .type sym, @object; \ 92 | .align 2; \ 93 | sym: .word word; 94 | 95 | #define DEFINE_GLOBAL_WORD(sym, word) \ 96 | .globl sym; \ 97 | .type sym, @common; \ 98 | .align 2; \ 99 | sym: .word word 100 | 101 | #define DEFINE_LONG(sym, long) \ 102 | .type sym, @object; \ 103 | .align 2; \ 104 | sym: .long long; 105 | 106 | #define DEFINE_GLOBAL_LONG(sym, long) \ 107 | .globl sym; \ 108 | .align 2; \ 109 | .type sym, @common; \ 110 | sym: .long long 111 | 112 | /* 113 | * Pseudo-instruction sets for compatibility 114 | * 115 | * Instruction not listed here doesn't have compatibility issues and 116 | * can be used as is. 117 | */ 118 | 119 | #if defined(_MIPS_ARCH_MIPS32) || defined(_MIPS_ARCH_MIPS32R2) 120 | /* Load constant, See MIPS Run 8.7.3 */ 121 | # define LA la 122 | # define LI li 123 | /* Addition and subtraction, See MIPS Run 8.7.4 */ 124 | # define ADD add 125 | # define ADDI addi 126 | # define ADDU addu 127 | # define ADDIU addiu 128 | # define SUB sub 129 | # define SUBU subu 130 | /* Register shifts & rotates */ 131 | # define ROL rol 132 | # define ROR ror 133 | # define SLL sll 134 | # define SRA sra 135 | # define SRL srl 136 | /* Multiplication and division, See MIPS Run 8.7.5 */ 137 | # define DIV div 138 | # define DIVU divu 139 | # define MUL mul 140 | # define MULT mult 141 | # define MULTU multu 142 | # define REM rem 143 | # define REMU remu 144 | /* Load and Store, See MIPS Run 8.7.7 */ 145 | # define LOAD lw 146 | # define STORE sw 147 | # define LOADL lwl 148 | # define LOADR lwr 149 | # define STOREL swl 150 | # define STORER swr 151 | # define ULOAD ulw 152 | # define USTORE usw 153 | /* Load-link and Store-conditional */ 154 | # define LL ll 155 | # define SC sc 156 | /* 157 | * CP0 Transfers, See MIPS Run 8.7.10. 158 | * 159 | * Be sure to check the width of CP0 registers on MIPS64 CPUs, as not all 160 | * CP0 registers are 64-bit there. 161 | * 162 | * For example, CP0_STATUS and CP0_CAUSE are always 32-bit, but 163 | * CP0_EPC is 64-bit on MIPS64. 164 | */ 165 | # define MFC0 mfc0 166 | # define MTC0 mtc0 167 | #elif defined(_MIPS_ARCH_MIPS64) || defined(_MIPS_ARCH_MIPS64R2) 168 | /* Load constant, See MIPS Run 8.7.3 */ 169 | # define LA dla 170 | # define LI dli 171 | /* Addition and subtraction, See MIPS Run 8.7.4 */ 172 | # define ADD dadd 173 | # define ADDI daddi 174 | # define ADDU daddu 175 | # define ADDIU daddiu 176 | # define SUB dsub 177 | # define SUBU dsubu 178 | /* Register shifts & rotates */ 179 | # define ROL drol 180 | # define ROR dror 181 | # define SLL dsll 182 | # define SRA dsra 183 | # define SRL dsrl 184 | /* Multiplication and division, See MIPS Run 8.7.5 */ 185 | # define DIV ddiv 186 | # define DIVU ddivu 187 | # define MUL dmul 188 | # define MULT dmult 189 | # define MULTU dmultu 190 | # define REM drem 191 | # define REMU dremu 192 | /* Load and Store, See MIPS Run 8.7.7 */ 193 | # define LOAD ld 194 | # define STORE sd 195 | # define LOADL ldl 196 | # define LOADR ldr 197 | # define STOREL sdl 198 | # define STORER sdr 199 | # define ULOAD uld 200 | # define USTORE usd 201 | /* Load-link and Store-conditional */ 202 | # define LL lld 203 | # define SC scd 204 | /* CP0 Transfers, See MIPS Run 8.7.10 */ 205 | # define MFC0 dmfc0 206 | # define MTC0 dmtc0 207 | #endif 208 | -------------------------------------------------------------------------------- /drivers/ata/ahci.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | static unsigned long ahci_current_rambase = AHCIPHY; 19 | 20 | static bool ahci_port_startable(volatile struct ahci_hba_port *port) 21 | { 22 | unsigned int tfd_stat = ahci_port_tfd_status(port); 23 | unsigned int sstatus_det = port->sstatus & PORT_SSTAT_DET_MASK; 24 | unsigned int sstatus_ipm = port->sstatus & PORT_SSTAT_IPM_MASK; 25 | 26 | return (!(port->cmd & PORT_CMD_CR) && 27 | !(tfd_stat & FIS_STAT_BUSY) && 28 | !(tfd_stat & FIS_STAT_DRQ) && 29 | ((sstatus_det == PORT_SSTAT_DET_CONNECT) || 30 | (sstatus_ipm == PORT_SSTAT_IPM_PARTIAL) || 31 | (sstatus_ipm == PORT_SSTAT_IPM_SLUMBER) || 32 | (sstatus_ipm == PORT_SSTAT_IPM_DEVSLP))); 33 | } 34 | 35 | static inline void ahci_wait_port(volatile struct ahci_hba_port *port) 36 | { 37 | unsigned int stat; 38 | 39 | do { 40 | stat = ahci_port_tfd_status(port); 41 | } while (stat & (FIS_STAT_BUSY | FIS_STAT_DRQ | FIS_STAT_ERR)); 42 | } 43 | 44 | static void ahci_port_start(volatile struct ahci_hba_port *port) 45 | { 46 | while (!ahci_port_startable(port)) 47 | /* nothing */; 48 | port->cmd |= PORT_CMD_FRE; 49 | port->cmd |= PORT_CMD_START; 50 | } 51 | 52 | void ahci_identify_device(volatile struct ahci_hba_port *port) 53 | { 54 | /* Take command slot 0 */ 55 | unsigned int clb = port->clb; 56 | unsigned int csb = clb - AHCI_CLB_OFFSET; 57 | unsigned int db = clb - AHCI_CLB_OFFSET + AHCI_DATA_OFFSET; 58 | struct ahci_cmdhdr *ch = (struct ahci_cmdhdr *)p2kv(clb); 59 | struct ahci_cmdslot *cs = (struct ahci_cmdslot *)p2kv(csb); 60 | unsigned short *data = (unsigned short *)p2kv(db); 61 | unsigned int fb = port->fb; 62 | int i; 63 | 64 | /* Fill in PRD */ 65 | memset(cs, 0, sizeof(*cs)); 66 | cs->prd[0].dba = db; 67 | cs->prd[0].dbc = 256 * sizeof(unsigned short) - 1; /* 256 words */ 68 | /* 69 | * Fill in command table. 70 | * We need to send the IDENTIFY DEVICE command to HBA. 71 | */ 72 | cs->ct.cfis.type = FIS_H2D_REG; 73 | cs->ct.cfis.event = FIS_WRITE_CMD; 74 | cs->ct.cfis.cmd = ATA_IDENTIFY_DEVICE; 75 | cs->ct.cfis.lba.mode = 1; 76 | cs->ct.cfis.nsec_l = 1; 77 | 78 | /* Fill in command header */ 79 | memset(ch, 0, sizeof(*ch)); 80 | ch->cfl = sizeof(cs->ct.cfis) / sizeof(unsigned int); 81 | ch->clear_on_ok = 1; 82 | ch->prdtl = 1; 83 | ch->prefetch = 1; 84 | ch->ctba = kv2p(&cs->ct); 85 | ch->ctbau = 0; 86 | 87 | ahci_wait_port(port); 88 | memset(data, 0, sizeof(*data) * 256); 89 | 90 | /* Issue command! */ 91 | port->cmd_issue = 1; 92 | 93 | /* Wait for command to complete */ 94 | do { 95 | if (port->intr_status) { 96 | pdebug("\t\tInterrupt status %08x\r\n", 97 | port->intr_status); 98 | pdebug("\t\tSError %08x\r\n", port->serror); 99 | delay(10000); 100 | } 101 | } while (port->cmd_issue & 1); 102 | if (port->intr_status) { 103 | pdebug("\t\tInterrupt status %08x\r\n", 104 | port->intr_status); 105 | pdebug("\t\tSError %08x\r\n", port->serror); 106 | delay(10000); 107 | } 108 | 109 | /* Read data stored at the location indicated by PRD */ 110 | uart_spin_printf("\t\tIdentification Data\r\n"); 111 | for (i = 0; i < 256; ++i, ++data) 112 | uart_spin_printf("%04x%s", *data, (i + 1) % 8 ? " " : "\r\n"); 113 | 114 | uart_spin_printf("%02x\r\n", *(unsigned char *)p2kv(fb)); 115 | } 116 | 117 | /* 118 | * ahci_init_port(port): 119 | * Software initialization of HBA port 120 | * 121 | * Parameters: 122 | * @port The HBA port structure 123 | * @serror Returns SError register 124 | * 125 | * Return value: 126 | * Zero if success, or -ENODEV if failure 127 | * 128 | * Reference: 129 | * SATA 1.3 specification 130 | */ 131 | int ahci_init_port(volatile struct ahci_hba_port *port, unsigned int *serror) 132 | { 133 | /* Physical address of a temporary FIS buffer */ 134 | unsigned int sstatus_det; 135 | unsigned long fb = ahci_current_rambase + AHCI_FB_OFFSET; 136 | unsigned long clb = ahci_current_rambase + AHCI_CLB_OFFSET; 137 | struct fis_recvbuf *fb_buf = (struct fis_recvbuf *)p2kv(fb); 138 | 139 | /* Halt FIS and command processing */ 140 | port->cmd &= ~(PORT_CMD_FRE | PORT_CMD_START); 141 | while (port->cmd & (PORT_CMD_CR | PORT_CMD_FR)) 142 | /* nothing */; 143 | 144 | /* Reset port */ 145 | port->scontrol = (port->scontrol & ~PORT_SCNTL_DET_MASK) | 146 | PORT_SCNTL_DET_RESET; 147 | delay(1); 148 | port->scontrol = (port->scontrol & ~PORT_SCNTL_DET_MASK) | 149 | PORT_SCNTL_DET_NONE; 150 | 151 | /* TODO: initialize FIS buffer */ 152 | memset(fb_buf, 0, sizeof(*fb_buf)); 153 | port->fbu = 0; 154 | port->fb = fb; 155 | 156 | /* Enable FIS reception and spinup */ 157 | port->cmd |= PORT_CMD_FRE | PORT_CMD_SUD; 158 | 159 | /* Wait and see if device could be connected */ 160 | delay(1000); 161 | sstatus_det = port->sstatus & PORT_SSTAT_DET_MASK; 162 | switch (sstatus_det) { 163 | case PORT_SSTAT_DET_NONE: 164 | case PORT_SSTAT_DET_OFFLINE: 165 | return -ENODEV; 166 | break; 167 | case PORT_SSTAT_DET_PRESENT: 168 | case PORT_SSTAT_DET_CONNECT: 169 | if (serror != NULL) 170 | *serror = port->serror; 171 | port->serror = 0; 172 | port->intr_status = 0; 173 | 174 | uart_spin_printf("Signature: %08x\r\n", port->sig); 175 | 176 | pdebug("Waiting...\r\n"); 177 | ahci_wait_port(port); 178 | 179 | /* Specify command list buffer */ 180 | port->clbu = 0; 181 | port->clb = clb; 182 | 183 | ahci_port_start(port); 184 | pdebug("Port started\r\n"); 185 | 186 | ahci_identify_device(port); 187 | 188 | ahci_current_rambase += AHCI_PORT_RAM_SIZE; 189 | return 0; 190 | break; 191 | default: 192 | /* NOTREACHED */ 193 | return -EINVAL; 194 | break; 195 | } 196 | } 197 | 198 | -------------------------------------------------------------------------------- /drivers/clock/mc146818.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2002 Opsycon AB (www.opsycon.se / www.opsycon.com) 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 3. All advertising materials mentioning features or use of this software 13 | * must display the following acknowledgement: 14 | * This product includes software developed by Opsycon AB, Sweden. 15 | * 4. The name of the author may not be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 19 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 | * SUCH DAMAGE. 29 | * 30 | * Copyright (C) 2015 Gan Quan 31 | * 32 | * This program is free software; you can redistribute it and/or modify it 33 | * under the terms of the GNU General Public License as published by the 34 | * Free Software Foundation; either version 2 of the License, or (at your 35 | * option) any later version. 36 | * 37 | */ 38 | #ifndef _DRIVERS_CLOCK_MC146818_H 39 | #define _DRIVERS_CLOCK_MC146818_H 40 | 41 | /* 42 | * Register definitions for Dallas Semiconductor DS17285/287 clock chips. 43 | */ 44 | 45 | #define DS_REG_SEC 0x00 /* Seconds reg */ 46 | #define DS_REG_ASEC 0x01 /* Alarm Seconds reg */ 47 | #define DS_REG_MIN 0x02 /* Minutes reg */ 48 | #define DS_REG_AMIN 0x03 /* Alarm Minutes reg */ 49 | #define DS_REG_HOUR 0x04 /* Hours reg */ 50 | #define DS_REG_AHOUR 0x05 /* Alarm Hours reg */ 51 | #define DS_REG_WDAY 0x06 /* Day of week reg */ 52 | #define DS_REG_DATE 0x07 /* Day of month reg */ 53 | #define DS_REG_MONTH 0x08 /* Month reg */ 54 | #define DS_REG_YEAR 0x09 /* Year reg */ 55 | 56 | #define DS_REG_CTLA 0x0a /* Control reg A */ 57 | #define DS_REG_CTLB 0x0b /* Control reg B */ 58 | #define DS_REG_CTLC 0x0c /* Control reg C */ 59 | #define DS_REG_CTLD 0x0d /* Control reg D */ 60 | 61 | 62 | #define DS_MONTH_E32K 0x40 /* Enable 32Khz out when 0 */ 63 | #define DS_MONTH_EOSC 0x80 /* Enable oscilator when 0 */ 64 | 65 | #define DS_CTLA_RS0 0x01 /* Rate Select */ 66 | #define DS_CTLA_RS1 0x02 /* Rate Select */ 67 | #define DS_CTLA_RS2 0x04 /* Rate Select */ 68 | #define DS_CTLA_RS3 0x08 /* Rate Select */ 69 | #define DS_CTLA_DV0 0x10 /* Bank Select */ 70 | #define DS_CTLA_DV1 0x20 /* Osc. Enable */ 71 | #define DS_CTLA_DV2 0x40 /* Countdown Chain */ 72 | #define DS_CTLA_UIP 0x80 /* Update In Progress flag 1 */ 73 | 74 | #define DS_CTLB_DSE 0x01 /* Daylight savings enable */ 75 | #define DS_CTLB_24 0x02 /* 24hr enable */ 76 | #define DS_CTLB_DM 0x04 /* Data mode */ 77 | #define DS_CTLB_SQWE 0x08 /* Square wave enable */ 78 | #define DS_CTLB_UIE 0x10 /* Update ended interrupt enable */ 79 | #define DS_CTLB_AIE 0x20 /* Alarm interrupt enable */ 80 | #define DS_CTLB_PIE 0x40 /* Periodic interrupt enable */ 81 | #define DS_CTLB_SET 0x80 /* Set registers enable */ 82 | 83 | /* 84 | * Registers in Bank 1 85 | */ 86 | 87 | #define DS_REG_CENT 0x48 /* Century reg */ 88 | 89 | #define DS_EXRAM_LSB 0x50 /* Extended RAM LSB addr */ 90 | #define DS_EXRAM_MSB 0x51 /* Extended RAM MSB addr */ 91 | #define DS_EXRAM_DATA 0x53 /* Extended RAM Data port */ 92 | 93 | #define PCI_RTC_ADDR_REG 0x70 /* RTC address PCI register */ 94 | #define PCI_RTC_DATA_REG 0x71 /* RTC data PCI register */ 95 | 96 | #include 97 | 98 | /* 99 | * readreg() and writereg() are for writing *raw* values. For time 100 | * registers, that means to write value in BCD form. 101 | */ 102 | static inline unsigned char rtc_readreg(unsigned char reg) 103 | { 104 | outb(PCI_RTC_ADDR_REG, reg); 105 | return inb(PCI_RTC_DATA_REG); 106 | } 107 | 108 | static inline void rtc_writereg(unsigned char reg, unsigned char val) 109 | { 110 | outb(PCI_RTC_ADDR_REG, reg); 111 | outb(PCI_RTC_DATA_REG, val); 112 | } 113 | 114 | void rtc_init(void); 115 | 116 | static inline unsigned char bcd_to_byte(unsigned char bcd) 117 | { 118 | return ((bcd & 0xF) + ((bcd >> 4) & 0xF) * 10); 119 | } 120 | 121 | static inline unsigned char byte_to_bcd(unsigned char byte) 122 | { 123 | return ((((byte / 10) % 10) << 4) + (byte % 10)); 124 | } 125 | 126 | /* 127 | * gettimereg() reads time registers and converts them from BCD to integer. 128 | * settimereg() converts the value to BCD and writes to time registers. 129 | */ 130 | unsigned char rtc_gettimereg(unsigned char reg); 131 | void rtc_settimereg(unsigned char reg, unsigned char val); 132 | 133 | #define rtc_getcentury() rtc_gettimereg(DS_REG_CENT) 134 | #define rtc_getyearshort() rtc_gettimereg(DS_REG_YEAR) 135 | #define rtc_getmonth() rtc_gettimereg(DS_REG_MONTH) 136 | #define rtc_getday() rtc_gettimereg(DS_REG_DATE) 137 | #define rtc_getdayofweek() rtc_gettimereg(DS_REG_WDAY) 138 | #define rtc_gethour() rtc_gettimereg(DS_REG_HOUR) 139 | #define rtc_getminute() rtc_gettimereg(DS_REG_MIN) 140 | #define rtc_getsecond() rtc_gettimereg(DS_REG_SEC) 141 | 142 | #define rtc_getyear() \ 143 | ((unsigned int)rtc_getcentury() * 100 + rtc_getyearshort()) 144 | 145 | #define rtc_setcentury(v) rtc_settimereg(DS_REG_CENT, v) 146 | #define rtc_setyearshort(v) rtc_settimereg(DS_REG_YEAR, v) 147 | #define rtc_setmonth(v) rtc_settimereg(DS_REG_MONTH, v) 148 | #define rtc_setday(v) rtc_settimereg(DS_REG_DATE, v) 149 | #define rtc_setdayofweek(v) rtc_settimereg(DS_REG_WDAY, v) 150 | #define rtc_sethour(v) rtc_settimereg(DS_REG_HOUR, v) 151 | #define rtc_setminute(v) rtc_settimereg(DS_REG_MIN, v) 152 | #define rtc_setsecond(v) rtc_settimereg(DS_REG_SEC, v) 153 | 154 | #define rtc_setyear(v) \ 155 | do { \ 156 | rtc_setcentury((v) / 100); \ 157 | rtc_setyearshort((v) % 100); \ 158 | } while (0) 159 | 160 | #endif /* _DRIVERS_RTC_MC146818_H */ 161 | 162 | -------------------------------------------------------------------------------- /include/arch/mips64/asm/cp0regdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle 3 | * Copyright (C) 2000 Silicon Graphics, Inc. 4 | * Modified for further R[236]000 support by Paul M. Antoine, 1996. 5 | * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com 6 | * Copyright (C) 2000, 07 MIPS Technologies, Inc. 7 | * Copyright (C) 2003, 2004 Maciej W. Rozycki 8 | * 9 | * Copyright (C) 2015, Gan Quan 10 | */ 11 | #ifndef _ASM_CP0REGDEF_H 12 | #define _ASM_CP0REGDEF_H 13 | 14 | #define CP0_INDEX $0 15 | #define CP0_RANDOM $1 16 | #define CP0_ENTRYLO0 $2 17 | #define CP0_ENTRYLO1 $3 18 | #define CP0_CONTEXT $4 19 | #define CP0_PAGEMASK $5 20 | # define CP0_PAGEGRAIN $5, 1 21 | #define CP0_WIRED $6 22 | #define CP0_HWRENA $7 23 | #define CP0_BADVADDR $8 /* Bad Virtual Address Register */ 24 | #define CP0_COUNT $9 /* Counter */ 25 | #define CP0_ENTRYHI $10 26 | #define CP0_COMPARE $11 /* Comparer: raises interrupt when = $9 */ 27 | #define CP0_STATUS $12 /* Status Register */ 28 | # define CP0_INTCTL $12, 1 /* Interrupt control */ 29 | # define CP0_SRSCTL $12, 2 30 | # define CP0_SRSMAP $12, 3 31 | #define CP0_CAUSE $13 /* Cause Register */ 32 | #define CP0_EPC $14 /* Exception Program Counter */ 33 | #define CP0_PRID $15 34 | # define CP0_EBASE $15, 1 /* Exception base, and CPU ID for multicore */ 35 | #define CP0_CONFIG $16 36 | # define CP0_CONFIG1 $16, 1 37 | # define CP0_CONFIG2 $16, 2 38 | # define CP0_CONFIG3 $16, 3 39 | #define CP0_LLADDR $17 40 | #define CP0_WATCHLO $18 41 | #define CP0_WATCHHI $19 42 | #define CP0_XCONTEXT $20 43 | #define CP0_FRAMEMASK $21 44 | #define CP0_DIAGNOSTIC $22 45 | #define CP0_PERFCTL $25 46 | # define CP0_PERFCNT $25, $1 47 | #define CP0_ECC $26 48 | #define CP0_CACHEERR $27 49 | # define CP0_CERRADDR $27, $1 50 | #define CP0_TAGLO $28 51 | # define CP0_DATALO $28, $1 52 | #define CP0_TAGHI $29 53 | # define CP0_DATAHI $29, $1 54 | #define CP0_ERROREPC $30 55 | #define CP0_DESAVE $31 56 | 57 | /* 58 | * Status register (CP0_STATUS) mode bits 59 | */ 60 | #define ST_CU3 0x80000000 /* Coprocessor 3 (MIPS IV User Mode) */ 61 | #define ST_CU2 0x40000000 /* Coprocessor 2 */ 62 | #define ST_CU1 0x20000000 /* Coprocessor 1 (FPU) */ 63 | #define ST_CU0 0x10000000 /* Coprocessor 0 (this one) */ 64 | #define ST_RP 0x08000000 /* Reduce power */ 65 | #define ST_FR 0x04000000 /* Float register mode switch (?) */ 66 | #define ST_RE 0x02000000 /* Reverse-endian */ 67 | #define ST_MX 0x01000000 /* Enable DSP or MDMX */ 68 | #define ST_PX 0x00800000 /* Enable 64-bit operations in user mode */ 69 | /* The exception handler would be at 0xbfc00000 if BEV=1, 0x80000000 70 | * otherwise */ 71 | #define ST_BEV 0x00400000 /* Bootstrap Exception Vector, usually 0 */ 72 | #define ST_TS 0x00200000 /* TLB SHUTDOWN */ 73 | #define ST_SR 0x00100000 /* Soft Reset */ 74 | #define ST_NMI 0x00080000 /* Non-maskable Interrupt */ 75 | /* Interrupt Masks */ 76 | #define ST_IM 0x0000ff00 /* All interrupt masks */ 77 | #define ST_IMx(i) (1 << ((i) + 8)) 78 | /* eXtended addressing bits for 64-bit addresses */ 79 | #define ST_KX 0x00000080 /* Kernel mode eXtended addressing */ 80 | #define ST_SX 0x00000040 /* Supervisor mode eXtended addressing */ 81 | #define ST_UX 0x00000020 /* User mode eXtended addressing */ 82 | /* 83 | * This mask is helpful since clearing these bits in exception handler 84 | * guarantees that: 85 | * 1. The processor runs in kernel mode. 86 | * 2. The processor is safe from interrupts. 87 | * 3. The processor rewrites EPC when a nested exception occur. 88 | * 4. The processor can safely return to previous handler after dealing 89 | * with nested ones. 90 | */ 91 | #define ST_EXCM 0x0000001f /* Status Register EXception Clear Mask */ 92 | /* Kernel/Supervisor/User mode switch */ 93 | #define ST_KSU 0x00000018 /* KSU switch */ 94 | # define KSU_USER 0x00000010 /* User mode */ 95 | # define KSU_SUPERVISOR 0x00000008 /* Supervisor mode */ 96 | # define KSU_KERNEL 0x00000000 /* Kernel mode */ 97 | #define ST_ERL 0x00000004 /* Error Level */ 98 | #define ST_EXL 0x00000002 /* Exception Level */ 99 | #define ST_IE 0x00000001 /* Global Interrupt Enable */ 100 | 101 | #define NR_INTS 8 /* Number of Interrupt Mask Bits */ 102 | 103 | /* 104 | * Cause register (CP0_CAUSE) bits, for handling exceptions 105 | */ 106 | 107 | /* Branch Delay would be set if an exception occur in the delay slot, while 108 | * EPC points to the branching instruction. */ 109 | #define CR_BD 0x80000000 /* Branch Delay */ 110 | #define CR_TI 0x40000000 /* Timer Interrupt */ 111 | #define CR_CE 0x30000000 /* Coprocessor Error */ 112 | #define CR_DC 0x08000000 /* Disable Counter */ 113 | #define CR_PCI 0x04000000 /* CP0 Performance Counter Overflow (?) */ 114 | #define CR_IV 0x00800000 /* Interrupt Vector */ 115 | #define CR_WP 0x00400000 /* Watchpoint */ 116 | #define CR_IP 0x0000ff00 /* Interrupt Pending */ 117 | #define CR_IPx(i) (1 << ((i + 8))) 118 | #define CR_EC 0x0000007c /* Exception Code */ 119 | #define EXCCODE(x) (((x) & CR_EC) >> 2) 120 | 121 | /* 122 | * Exception codes 123 | */ 124 | #define EC_int 0 125 | #define EC_tlbm 1 126 | #define EC_tlbl 2 127 | #define EC_tlbs 3 128 | #define EC_adel 4 129 | #define EC_ades 5 130 | #define EC_ibe 6 131 | #define EC_dbe 7 132 | #define EC_sys 8 133 | #define EC_bp 9 134 | #define EC_ri 10 135 | #define EC_cpu 11 136 | #define EC_ov 12 137 | #define EC_tr 13 138 | #define EC_fpe 15 139 | #define EC_is 16 140 | #define EC_dib 19 141 | #define EC_ddbs 20 142 | #define EC_ddbl 21 143 | #define EC_watch 23 144 | #define EC_dbp 26 145 | #define EC_dint 27 146 | #define EC_dss 28 147 | #define EC_cacheerr 30 148 | 149 | /* 150 | * PageMask register 151 | */ 152 | 153 | #define PM_4K 0x00000000 154 | #define PM_8K 0x00002000 155 | #define PM_16K 0x00006000 156 | #define PM_32K 0x0000e000 157 | #define PM_64K 0x0001e000 158 | #define PM_128K 0x0003e000 159 | #define PM_256K 0x0007e000 160 | #define PM_512K 0x000fe000 161 | #define PM_1M 0x001fe000 162 | #define PM_2M 0x003fe000 163 | #define PM_4M 0x007fe000 164 | #define PM_8M 0x00ffe000 165 | #define PM_16M 0x01ffe000 166 | #define PM_32M 0x03ffe000 167 | #define PM_64M 0x07ffe000 168 | #define PM_256M 0x1fffe000 169 | #define PM_1G 0x7fffe000 170 | 171 | /* 172 | * PageGrain register used by Loongson 3A 173 | */ 174 | 175 | #define PG_ELPA 0x20000000 /* Enable Large Page Address */ 176 | 177 | /* 178 | * Config register 179 | */ 180 | #define CONF_CM 0x80000000 /* Config1 register (FPU) */ 181 | #define CONF_BE 0x00008000 /* Big-endianness */ 182 | #define CONF_AT 0x00006000 /* MIPS Architecture */ 183 | # define CONF_EM 0x00004000 /* MIPS64 with 64-bit address space */ 184 | # define CONF_EB 0x00002000 /* MIPS64 with 32-bit address space */ 185 | #define CONF_AR 0x00001c00 /* MIPS release version */ 186 | # define CONF_R2 0x00000400 /* MIPSr2 */ 187 | #define CONF_MT 0x00000380 /* MMU type */ 188 | # define CONF_TLB 0x00000080 /* Standard TLB */ 189 | #define CONF_VI 0x00000008 /* Virtual instruction cache */ 190 | #define CONF_K0 0x00000007 /* KSEG0 cache consistency */ 191 | # define CONF_CACHEABLE 0x00000003 /* Cacheable */ 192 | # define CONF_UNCACHED 0x00000002 /* Uncached */ 193 | 194 | #define EBASE_CPUNUM_MASK 0x3ff 195 | 196 | #define ENTHI_ASID_MASK 0xff 197 | #define ENTHI_KSU_MASK 0xc000000000000000ULL 198 | 199 | #endif 200 | -------------------------------------------------------------------------------- /kern/arch/mips64/include/asm/cp0regdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle 3 | * Copyright (C) 2000 Silicon Graphics, Inc. 4 | * Modified for further R[236]000 support by Paul M. Antoine, 1996. 5 | * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com 6 | * Copyright (C) 2000, 07 MIPS Technologies, Inc. 7 | * Copyright (C) 2003, 2004 Maciej W. Rozycki 8 | * 9 | * Copyright (C) 2015, Gan Quan 10 | */ 11 | #ifndef _ASM_CP0REGDEF_H 12 | #define _ASM_CP0REGDEF_H 13 | 14 | #define CP0_INDEX $0 15 | #define CP0_RANDOM $1 16 | #define CP0_ENTRYLO0 $2 17 | #define CP0_ENTRYLO1 $3 18 | #define CP0_CONTEXT $4 19 | #define CP0_PAGEMASK $5 20 | # define CP0_PAGEGRAIN $5, 1 21 | #define CP0_WIRED $6 22 | #define CP0_HWRENA $7 23 | #define CP0_BADVADDR $8 /* Bad Virtual Address Register */ 24 | #define CP0_COUNT $9 /* Counter */ 25 | #define CP0_ENTRYHI $10 26 | #define CP0_COMPARE $11 /* Comparer: raises interrupt when = $9 */ 27 | #define CP0_STATUS $12 /* Status Register */ 28 | # define CP0_INTCTL $12, 1 /* Interrupt control */ 29 | # define CP0_SRSCTL $12, 2 30 | # define CP0_SRSMAP $12, 3 31 | #define CP0_CAUSE $13 /* Cause Register */ 32 | #define CP0_EPC $14 /* Exception Program Counter */ 33 | #define CP0_PRID $15 34 | # define CP0_EBASE $15, 1 /* Exception base, and CPU ID for multicore */ 35 | #define CP0_CONFIG $16 36 | # define CP0_CONFIG1 $16, 1 37 | # define CP0_CONFIG2 $16, 2 38 | # define CP0_CONFIG3 $16, 3 39 | #define CP0_LLADDR $17 40 | #define CP0_WATCHLO $18 41 | #define CP0_WATCHHI $19 42 | #define CP0_XCONTEXT $20 43 | #define CP0_FRAMEMASK $21 44 | #define CP0_DIAGNOSTIC $22 45 | #define CP0_PERFCTL $25 46 | # define CP0_PERFCNT $25, $1 47 | #define CP0_ECC $26 48 | #define CP0_CACHEERR $27 49 | # define CP0_CERRADDR $27, $1 50 | #define CP0_TAGLO $28 51 | # define CP0_DATALO $28, $1 52 | #define CP0_TAGHI $29 53 | # define CP0_DATAHI $29, $1 54 | #define CP0_ERROREPC $30 55 | #define CP0_DESAVE $31 56 | 57 | /* 58 | * Status register (CP0_STATUS) mode bits 59 | */ 60 | #define ST_CU3 0x80000000 /* Coprocessor 3 (MIPS IV User Mode) */ 61 | #define ST_CU2 0x40000000 /* Coprocessor 2 */ 62 | #define ST_CU1 0x20000000 /* Coprocessor 1 (FPU) */ 63 | #define ST_CU0 0x10000000 /* Coprocessor 0 (this one) */ 64 | #define ST_RP 0x08000000 /* Reduce power */ 65 | #define ST_FR 0x04000000 /* Float register mode switch (?) */ 66 | #define ST_RE 0x02000000 /* Reverse-endian */ 67 | #define ST_MX 0x01000000 /* Enable DSP or MDMX */ 68 | #define ST_PX 0x00800000 /* Enable 64-bit operations in user mode */ 69 | /* The exception handler would be at 0xbfc00000 if BEV=1, 0x80000000 70 | * otherwise */ 71 | #define ST_BEV 0x00400000 /* Bootstrap Exception Vector, usually 0 */ 72 | #define ST_TS 0x00200000 /* TLB SHUTDOWN */ 73 | #define ST_SR 0x00100000 /* Soft Reset */ 74 | #define ST_NMI 0x00080000 /* Non-maskable Interrupt */ 75 | /* Interrupt Masks */ 76 | #define ST_IM 0x0000ff00 /* All interrupt masks */ 77 | #define ST_IMx(i) (1 << ((i) + 8)) 78 | /* eXtended addressing bits for 64-bit addresses */ 79 | #define ST_KX 0x00000080 /* Kernel mode eXtended addressing */ 80 | #define ST_SX 0x00000040 /* Supervisor mode eXtended addressing */ 81 | #define ST_UX 0x00000020 /* User mode eXtended addressing */ 82 | /* 83 | * This mask is helpful since clearing these bits in exception handler 84 | * guarantees that: 85 | * 1. The processor runs in kernel mode. 86 | * 2. The processor is safe from interrupts. 87 | * 3. The processor rewrites EPC when a nested exception occur. 88 | * 4. The processor can safely return to previous handler after dealing 89 | * with nested ones. 90 | */ 91 | #define ST_EXCM 0x0000001f /* Status Register EXception Clear Mask */ 92 | /* Kernel/Supervisor/User mode switch */ 93 | #define ST_KSU 0x00000018 /* KSU switch */ 94 | # define KSU_USER 0x00000010 /* User mode */ 95 | # define KSU_SUPERVISOR 0x00000008 /* Supervisor mode */ 96 | # define KSU_KERNEL 0x00000000 /* Kernel mode */ 97 | #define ST_ERL 0x00000004 /* Error Level */ 98 | #define ST_EXL 0x00000002 /* Exception Level */ 99 | #define ST_IE 0x00000001 /* Global Interrupt Enable */ 100 | 101 | #define NR_INTS 8 /* Number of Interrupt Mask Bits */ 102 | 103 | /* 104 | * Cause register (CP0_CAUSE) bits, for handling exceptions 105 | */ 106 | 107 | /* Branch Delay would be set if an exception occur in the delay slot, while 108 | * EPC points to the branching instruction. */ 109 | #define CR_BD 0x80000000 /* Branch Delay */ 110 | #define CR_TI 0x40000000 /* Timer Interrupt */ 111 | #define CR_CE 0x30000000 /* Coprocessor Error */ 112 | #define CR_DC 0x08000000 /* Disable Counter */ 113 | #define CR_PCI 0x04000000 /* CP0 Performance Counter Overflow (?) */ 114 | #define CR_IV 0x00800000 /* Interrupt Vector */ 115 | #define CR_WP 0x00400000 /* Watchpoint */ 116 | #define CR_IP 0x0000ff00 /* Interrupt Pending */ 117 | #define CR_IPx(i) (1 << ((i + 8))) 118 | #define CR_EC 0x0000007c /* Exception Code */ 119 | #define EXCCODE(x) (((x) & CR_EC) >> 2) 120 | 121 | /* 122 | * Exception codes 123 | */ 124 | #define EC_int 0 125 | #define EC_tlbm 1 126 | #define EC_tlbl 2 127 | #define EC_tlbs 3 128 | #define EC_adel 4 129 | #define EC_ades 5 130 | #define EC_ibe 6 131 | #define EC_dbe 7 132 | #define EC_sys 8 133 | #define EC_bp 9 134 | #define EC_ri 10 135 | #define EC_cpu 11 136 | #define EC_ov 12 137 | #define EC_tr 13 138 | #define EC_fpe 15 139 | #define EC_is 16 140 | #define EC_dib 19 141 | #define EC_ddbs 20 142 | #define EC_ddbl 21 143 | #define EC_watch 23 144 | #define EC_dbp 26 145 | #define EC_dint 27 146 | #define EC_dss 28 147 | #define EC_cacheerr 30 148 | 149 | /* 150 | * PageMask register 151 | */ 152 | 153 | #define PM_4K 0x00000000 154 | #define PM_8K 0x00002000 155 | #define PM_16K 0x00006000 156 | #define PM_32K 0x0000e000 157 | #define PM_64K 0x0001e000 158 | #define PM_128K 0x0003e000 159 | #define PM_256K 0x0007e000 160 | #define PM_512K 0x000fe000 161 | #define PM_1M 0x001fe000 162 | #define PM_2M 0x003fe000 163 | #define PM_4M 0x007fe000 164 | #define PM_8M 0x00ffe000 165 | #define PM_16M 0x01ffe000 166 | #define PM_32M 0x03ffe000 167 | #define PM_64M 0x07ffe000 168 | #define PM_256M 0x1fffe000 169 | #define PM_1G 0x7fffe000 170 | 171 | /* 172 | * PageGrain register used by Loongson 3A 173 | */ 174 | 175 | #define PG_ELPA 0x20000000 /* Enable Large Page Address */ 176 | 177 | /* 178 | * Config register 179 | */ 180 | #define CONF_CM 0x80000000 /* Config1 register (FPU) */ 181 | #define CONF_BE 0x00008000 /* Big-endianness */ 182 | #define CONF_AT 0x00006000 /* MIPS Architecture */ 183 | # define CONF_EM 0x00004000 /* MIPS64 with 64-bit address space */ 184 | # define CONF_EB 0x00002000 /* MIPS64 with 32-bit address space */ 185 | #define CONF_AR 0x00001c00 /* MIPS release version */ 186 | # define CONF_R2 0x00000400 /* MIPSr2 */ 187 | #define CONF_MT 0x00000380 /* MMU type */ 188 | # define CONF_TLB 0x00000080 /* Standard TLB */ 189 | #define CONF_VI 0x00000008 /* Virtual instruction cache */ 190 | #define CONF_K0 0x00000007 /* KSEG0 cache consistency */ 191 | # define CONF_CACHEABLE 0x00000003 /* Cacheable */ 192 | # define CONF_UNCACHED 0x00000002 /* Uncached */ 193 | 194 | #define EBASE_CPUNUM_MASK 0x3ff 195 | 196 | #define ENTHI_ASID_MASK 0xff 197 | #define ENTHI_KSU_MASK 0xc000000000000000ULL 198 | 199 | #endif 200 | -------------------------------------------------------------------------------- /drivers/ata/ahci_fis.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | /* 12 | * This header contains Frame Info Structure (FIS) definition for AHCI 13 | * controller. 14 | * 15 | * References: 16 | * SATA 1.0a specification 17 | * http://www.ece.umd.edu/courses/enee759h.S2003/references/serialata10a.pdf 18 | * (Oddly, not available on Intel or sata-io.org) 19 | * 20 | * SATA 1.1 specification, available on Intel website 21 | * 22 | * SATA Storage Technology, Don Anderson, Mindshare, 2007 23 | * 24 | * ATAPI 7 Specifications, Volume 3, available at 25 | * https://ata.wiki.kernel.org/index.php/Developer_Resources 26 | */ 27 | 28 | #ifndef _DRIVERS_ATA_AHCI_FIS_H 29 | #define _DRIVERS_ATA_AHCI_FIS_H 30 | 31 | #include 32 | 33 | /* 34 | * FIS types 35 | */ 36 | #define FIS_H2D_REG 0x27 /* Host to Device Register */ 37 | #define FIS_D2H_REG 0x34 /* Device to Host Register */ 38 | #define FIS_SET_DEVICE_BITS 0xa1 /* D2H */ 39 | #define FIS_PIO_SETUP 0x5f /* D2H*/ 40 | #define FIS_DMA_ACTIVATE 0x39 /* D2H */ 41 | #define FIS_DMA_SETUP 0x41 /* Bidirectional */ 42 | #define FIS_DATA 0x46 /* Bidirectional */ 43 | #define FIS_BIST_ACTIVATE 0x58 /* Bidirectional */ 44 | 45 | /* CHS representation used by FIS */ 46 | struct fis_chs { 47 | /* DWORD 1 */ 48 | uchar sec; /* Sector [7..0] */ 49 | uchar cyl_l; /* Cylinder [7..0] */ 50 | uchar cyl_h; /* Cylinder [23..16] */ 51 | uchar head:4; /* Head */ 52 | uchar dev:1; /* Device */ 53 | uchar pad0:1; 54 | uchar mode:1; /* Must be 0 if in CHS mode */ 55 | uchar pad1:1; 56 | /* DWORD 2 */ 57 | uchar sec_e; /* Sector [15..8] */ 58 | uchar cyl_el; /* Cylinder [15..8] */ 59 | uchar cyl_eh; /* Cylinder [31..24] */ 60 | union { 61 | uchar feat_e; /* Features register [15..8] */ 62 | uchar rsvd; /* Not used */ 63 | }; 64 | }; 65 | 66 | /* LBA representation used by FIS */ 67 | struct fis_lba { 68 | /* DWORD 1 */ 69 | uchar lba0; /* LBA [7..0] */ 70 | uchar lba2; /* LBA [23..16] */ 71 | uchar lba4; /* LBA [39..32] */ 72 | uchar pad0:4; 73 | uchar dev:1; /* Device */ 74 | uchar pad1:1; 75 | uchar mode:1; /* Must be 1 if in LBA mode */ 76 | uchar pad2:1; 77 | /* DWORD 2 */ 78 | uchar lba1; /* LBA [15..8] */ 79 | uchar lba3; /* LBA [31..24] */ 80 | uchar lba5; /* LBA [47..40] */ 81 | union { 82 | uchar feat_e; /* Features register [15..8] */ 83 | uchar rsvd; /* Not used */ 84 | }; 85 | }; 86 | 87 | /* Host to Device - usually for writing */ 88 | struct fis_reg_h2d { 89 | /* DWORD 0 */ 90 | uchar type; /* FIS_H2D_REG */ 91 | uchar _pad0:7; 92 | uchar event:1; /* Transfer due to ... */ 93 | #define FIS_WRITE_CMD 1 94 | #define FIS_WRITE_CTRL 0 95 | uchar cmd; /* Command register */ 96 | uchar feat; /* Features register [7..0] */ 97 | /* DWORD 1-2 */ 98 | union { 99 | struct fis_chs chs; /* Cylinder-Head-Sector */ 100 | struct fis_lba lba; /* Logical Block Address */ 101 | }; 102 | /* DWORD 3 */ 103 | uchar nsec_l; /* Sector count [7..0] */ 104 | uchar nsec_h; /* Sector count [15..8] */ 105 | uchar pad1; 106 | uchar ctrl; /* Control register */ 107 | #define FIS_CTRL_HOB 0x80 /* High Order Byte */ 108 | #define FIS_CTRL_SRST 0x04 /* Soft Reset */ 109 | #define FIS_CTRL_nIEN 0x02 /* Disable interrupt */ 110 | /* DWORD 4 */ 111 | uint pad2; 112 | }; 113 | 114 | /* Device to Host - usually for reading */ 115 | struct fis_reg_d2h { 116 | /* DWORD 0 */ 117 | uchar type; /* FIS_D2H_REG */ 118 | uchar pad0:6; 119 | uchar intr:1; /* Interrupt bit */ 120 | uchar event:1; /* Transfer due to ... */ 121 | uchar status; /* Status register */ 122 | #define FIS_STAT_BUSY 0x80 /* Device busy */ 123 | #define FIS_STAT_DRDY 0x40 /* Device ready */ 124 | #define FIS_STAT_DF 0x20 /* Device fault */ 125 | #define FIS_STAT_SE 0x20 /* Stream error*/ 126 | #define FIS_STAT_SPEC 0x10 /* Command dependent */ 127 | #define FIS_STAT_DRQ 0x08 /* Data request */ 128 | #define FIS_STAT_ERR 0x01 /* Error reported */ 129 | #define FIS_STAT_CHK 0x01 /* Check exception */ 130 | uchar error; /* Error register */ 131 | #define FIS_ERROR_ABRT 0x04 /* Operation aborted */ 132 | /* DWORD 1-2 */ 133 | union { 134 | struct fis_chs chs; /* Cylinder-Head-Sector */ 135 | struct fis_lba lba; /* Logical Block Address */ 136 | }; 137 | /* DWORD 3 */ 138 | uchar nsec_l; /* Sector count [7..0] */ 139 | uchar nsec_h; /* Sector count [15..8] */ 140 | ushort pad1; 141 | /* DWORD 4 */ 142 | uint pad2; 143 | }; 144 | 145 | /* 146 | * Received when a Queued DMA R/W or a 1st party DMA R/W is executed. 147 | * Each field is identical to the fields in H2D/D2H FISes with the same name. 148 | */ 149 | struct fis_set_dev_bits { 150 | /* DWORD 0 */ 151 | uchar type; /* FIS_SET_DEVICE_BITS */ 152 | uchar pad0:5; 153 | uchar pad1:1; 154 | uchar intr:1; /* Interrupt bit */ 155 | uchar pad2:1; 156 | uchar status; /* Status register w/o BUSY and DRQ */ 157 | uchar error; /* Error register */ 158 | /* DWORD 1 */ 159 | union { 160 | uint pad3; 161 | uint sactive; /* SActive bitmap for NCQ */ 162 | }; 163 | }; 164 | 165 | struct fis_pio_setup { 166 | /* DWORD 0 */ 167 | uchar type; /* FIS_PIO_SETUP */ 168 | uchar pad0:5; 169 | uchar writemem:1; /* Host memory being written by dev */ 170 | uchar intr:1; /* Interrupt bit */ 171 | uchar pad1:1; 172 | uchar begin_status; /* Begin status */ 173 | uchar error; 174 | /* DWORD 1-2 */ 175 | union { 176 | struct fis_chs chs; 177 | struct fis_lba lba; 178 | }; 179 | /* DWORD 3 */ 180 | uchar nsec_l; 181 | uchar nsec_h; 182 | uchar pad2; 183 | uchar end_status; /* End status */ 184 | /* DWORD 4 */ 185 | ushort nbytes; /* a.k.a. Transfer Count */ 186 | ushort pad3; 187 | }; 188 | 189 | struct fis_dma_setup { 190 | /* DWORD 0 */ 191 | uchar type; /* FIS_DMA_SETUP */ 192 | uchar pad0:5; 193 | uchar dir:1; /* Direction */ 194 | #define FIS_DIR_SND2RCP 1 /* Sender to Recipient */ 195 | #define FIS_DIR_RCP2SND 0 /* Recipient to Sender */ 196 | uchar intr:1; /* Interrupt after transmission */ 197 | uchar auto_act:1; /* Auto-activate if supported */ 198 | ushort pad1; 199 | /* DWORD 1 */ 200 | union { 201 | uint dmabuf_l; /* DMA Buffer Identifier Low */ 202 | struct { 203 | uchar tag; /* TAG */ 204 | uint pad2:24; 205 | }; 206 | }; 207 | /* DWORD 2-6 */ 208 | uint dmabuf_h; /* DMA Buffer Identifier High */ 209 | uint pad3; 210 | uint dmabuf_off; /* DMA Buffer Offset */ 211 | uint transfer_count; /* DMA Transfer Count */ 212 | uint pad4; 213 | }; 214 | 215 | struct fis_dma_activate { 216 | /* DWORD 0 */ 217 | uchar type; /* FIS_DMA_ACTIVATE */ 218 | uint pad0:24; 219 | }; 220 | 221 | struct fis_dma_data { 222 | /* DWORD 0 */ 223 | uchar type; /* FIS_DMA_DATA */ 224 | uint pad0:24; 225 | /* May follow up to 2048 DWORDs */ 226 | }; 227 | 228 | struct fis_recvbuf { 229 | struct fis_dma_setup dsfis; 230 | uint pad0[1]; 231 | struct fis_pio_setup psfis; 232 | uint pad1[3]; 233 | struct fis_reg_d2h rfis; 234 | uint pad2[1]; 235 | struct fis_set_dev_bits sdbfis; 236 | unsigned char ufis[64]; 237 | unsigned char reserved[96]; 238 | }; 239 | #define AHCI_FIS_RECVBUF_SIZE sizeof(struct fis_recvbuf) 240 | 241 | #endif 242 | -------------------------------------------------------------------------------- /doc/labs/lab1-booting.markdown: -------------------------------------------------------------------------------- 1 | # Lab 1: Booting 2 | 3 | Booting is the very first process for a machine to startup, which can be 4 | roughly separated into two stages: 5 | 6 | 1. The CPU begins execution from BIOS or other ROM storage manufactured by 7 | OEM, performing early necessary hardware discovery (such as disk storage, 8 | serial, VGA, etc.) and self-tests. Normally this process is largely 9 | unchangeable except for a small set of configurations available through an 10 | interface. 11 | 2. After early discovery and self-tests, the program residing in BIOS or other 12 | ROM storage transfers control to a program called *bootloader*, which is 13 | stored on external storage such as hard disks, CD-ROMs, flash drives, while 14 | providing interfaces for convenient interactions with hardware such as BIOS 15 | interrupts. 16 | 17 | The installation of an operating system has the responsibility of properly 18 | setting up a bootloader. 19 | 20 | In this lab, we'll focus on MBR, a legacy booting scheme which is widely 21 | available (and sometimes the only option) on most machines. 22 | 23 | ### MBR 24 | 25 | Starting from PC-DOS 2.0 running on IBM PC with x86 instruction set, the 26 | bootloader is installed on the first sector of bootable external storage, 27 | which is called the *Master Boot Record* (MBR). 28 | 29 | The structure of MBR is described below: 30 | 31 | ```C 32 | #pragma pack (1) 33 | 34 | struct chs_address { /* cylinder-head-sector */ 35 | unsigned char head; /* head */ 36 | unsigned char sector:6; /* sector */ 37 | unsigned char cylinder_high:2; /* cylinder bit 9-8 */ 38 | unsigned char cylinder_low; /* cylinder bit 7-0 */ 39 | }; /* little-endian */ 40 | 41 | struct partition_entry { 42 | unsigned char status; /* partition status */ 43 | #define BOOTABLE 0x80 44 | #define INACTIVE 0x00 45 | /* 46 | * In CHS address, sectors start from 1 by convention, and the range 47 | * of head is 0-254. 48 | * 49 | * Usually CHS is insufficient to express a sector's address, in 50 | * which case the values are set to maximum. 51 | */ 52 | struct chs_address chs_first; /* CHS address of first sector */ 53 | unsigned char type; /* partition type code */ 54 | struct chs_address chs_last; /* CHS address of last sector */ 55 | unsigned int sec_first; /* No. of first sector */ 56 | unsigned int sec_count; /* Number of sectors */ 57 | }; 58 | 59 | struct mbr { 60 | unsigned char code[446]; /* bootloader code */ 61 | struct partition_entry pe[4]; /* 4 primary partitions */ 62 | unsigned char signature[2]; /* always 0x55 0xaa */ 63 | }; 64 | ``` 65 | 66 | The BIOS or other ROM storage loads the `code` member of MBR, that is, the 67 | first 446 bytes of the first sector on the external storage, into memory. 68 | 69 | Early bootloaders could fit themselves into the 446 bytes, but modern ones 70 | like GRUB certainly couldn't do so as they have to support lots of features. 71 | In this case, the 446 bytes contain only the *first stage* of the bootloader, 72 | whose purpose is mainly to load the *second stage* code stored elsewhere into 73 | memory and execute it. 74 | 75 | In our experiments, the bootloader code could **always** fit themselves into 76 | 446 bytes, regardless of architecture. 77 | 78 | ##### i386 79 | 80 | (TODO: add i386 bootloader code explanation) 81 | 82 | ##### armv7a-le 83 | 84 | (TODO: add armv7a-le bootloader code explanation) 85 | 86 | ##### MIPS64 87 | 88 | The original PMON, the BIOS for Loongson board, also took the role of 89 | bootloader (and therefore does not allow custom bootloader installation). 90 | We modified PMON to provide four helper functions and values, and to actually 91 | load and execute the code in MBR instead of finding the kernel directly: 92 | 93 | 1. `int fd` 94 | * An integer representing handle of the hard disk. 95 | 2. `void findsect(int fd, unsigned int sec)` 96 | * A function for locating the `sec`-th sector from start. 97 | 3. `int read(int fd, void *buf, unsigned int len)` 98 | * Identical to `read(2)` function. 99 | 4. `int lseek(int fd, unsigned int offset, int whence)` 100 | * Identical to `lseek(2)` function. 101 | 102 | The function and values are passed as arguments for the following bootloader 103 | entry function: 104 | 105 | ```C 106 | void boot(fd, findsect, read, lseek) 107 | ``` 108 | 109 | The bootloader code is in 110 | [bootsect.c](../../boot/arch/mips64/loongson3a/bootsect.c). 111 | After compilation, the function code itself is copied to the first 446 bytes 112 | of the first sector. 113 | 114 | PMON loads the entire MBR into memory starting at address 0x80100000, which 115 | becomes the entry address of bootloader code (`boot()` function). The 116 | partition entries could then be referred by simply adding an offset to the 117 | `boot()` function. 118 | 119 | We designed the bootloader to find the kernel, stored as ELF format, on the 120 | second partition. 121 | 122 | The bootloader does the following: 123 | 124 | 1. Find and locate the starting sector of second partition 125 | (`bootsect.c:63-83`). 126 | 2. Read the ELF header there 127 | (`bootsect.c:86-89`). 128 | 3. Find the number of program segments as well as the entry address 129 | (`bootsect.c:91-95`). 130 | 4. For each program segment, check if the segment is loadable as indicated 131 | in the *segment header* (also known as the *program header*) 132 | (`bootsect.c:98-108`). 133 | If the segment is indeed loadable, load the segment into memory at the 134 | address given in the segment header. 135 | 5. Jump to entry and begin execution of kernel. 136 | 137 | Because the encoding efficiency of MIPS instruction set is not as effective 138 | as that of i386, 446 bytes (that is, 111 instructions) could not do much job. 139 | We omitted verification, which is usually a vital process, to avoid introducing 140 | the second stage. 141 | 142 | ### Restrictions of MBR 143 | 144 | From knowledge above, we could find that legacy MBR method has the following 145 | restrictions: 146 | 147 | 1. **Limited (primary) partitions**, although *extended partition* type, which 148 | can hold several logical partitions, is introduced to resolve this issue. 149 | 2. **Limited disk size**, the 4-byte limit of sector count limits the disk 150 | size to be at most 2TB. 151 | 3. **Weak bootloader**, or even impossible to implement a bootloader without 152 | fine-grained help from BIOS on some RISC architectures. 153 | 154 | All these issues called for a new bootloading solution and a new partition 155 | scheme. *Unified Extensible Firmware Interface* (UEFI) as well as *GUID 156 | Partition Table* (GPT) are thus introduced. 157 | 158 | ### Exercises 159 | 160 | Assuming the repository is already cloned, and the current directory is 161 | the repository directory. 162 | 163 | 1. Switch branch to `lab1`. 164 | 2. Read and understand `Makefile` first. 165 | 3. After understanding `Makefile`, change configuration accordingly. 166 | 4. Compile with your choice of architecture by 167 | make ARCH= 168 | 5. Install to external storage by 169 | make ARCH= install 170 | One may have to plug in the external storage (SD card or SATA hard disk). 171 | Make sure the target device path is correct. 172 | 6. Open a serial and connect to the box. 173 | 7. Bring up the machine to see if you have correctly compiled and installed 174 | the kernel and bootloader. 175 | 8. Read the bootloader code (both C code, assembly code, and disassembly 176 | generated by `objdump`). Kernel code can be ignored at present. 177 | 178 | ###### i386 179 | 180 | (TODO) 181 | 182 | ###### armv7a-le 183 | 184 | (TODO) 185 | 186 | ###### MIPS64 187 | 188 | Loongson 3A box should emit a line 189 | Hello from kernel! 190 | and become idle. 191 | -------------------------------------------------------------------------------- /kern/arch/mips64/setup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* CPU pipeline frequency */ 18 | unsigned long cpu_freq; 19 | 20 | #define NR_FREQ_SAMPLES 4 21 | 22 | void probe_count_freq(void) 23 | { 24 | unsigned int cnt, cnt_new, i, sec; 25 | unsigned long count_inc; 26 | cnt = read_c0_count(); 27 | count_inc = 0; 28 | 29 | for (i = 0; i < NR_FREQ_SAMPLES + 1; ++i) { 30 | sec = rtc_getsecond(); 31 | cnt = read_c0_count(); 32 | do { 33 | cnt_new = read_c0_count(); 34 | } while (rtc_getsecond() == sec); 35 | if (i != 0) 36 | count_inc += cnt_new - cnt; 37 | } 38 | 39 | count_inc /= NR_FREQ_SAMPLES; 40 | 41 | /* 42 | * The rate of increasing COUNT register on MIPS really depends on 43 | * implementation. 44 | */ 45 | cpu_freq = COUNT_TO_FREQ(count_inc); 46 | } 47 | 48 | void clock_init(void) 49 | { 50 | printk("Initializing Real Time Clock (RTC)...\r\n"); 51 | rtc_init(); 52 | printk( 53 | "Current time: %04d-%02d-%02d %02d:%02d:%02d\r\n", 54 | rtc_getyear(), 55 | rtc_getmonth(), 56 | rtc_getday(), 57 | rtc_gethour(), 58 | rtc_getminute(), 59 | rtc_getsecond() 60 | ); 61 | 62 | printk("Determining CPU frequency...\r\n"); 63 | probe_count_freq(); 64 | printk("CPU frequency: %u\r\n", cpu_freq); 65 | } 66 | 67 | void usleep(unsigned int usec) 68 | { 69 | unsigned int cnt_incs = FREQ_TO_COUNT(cpu_freq / 1000000 * usec); 70 | unsigned int count = read_c0_count(); 71 | for (; read_c0_count() - count < cnt_incs; ) 72 | /* nothing */; 73 | } 74 | 75 | #if 1 76 | void setup_arch(void) 77 | { 78 | int i, j; 79 | uint32_t bar; 80 | int port = 0, slave = 0; 81 | uint8_t stat; 82 | 83 | /* Initialize hardware clocks */ 84 | clock_init(); 85 | 86 | uint32_t addr; 87 | uint64_t addr64; 88 | 89 | addr = 0x1a000000 | (0x11 << 11) | (0x40); 90 | out32(addr, in32(addr) | 0x1); 91 | 92 | addr = 0x1a000000 | (0x11 << 11) | (0x9); 93 | out8(addr, 0x8f); 94 | addr = 0x1a000000 | (0x11 << 11) | (0xa); 95 | out8(addr, 0x01); 96 | 97 | addr = 0x1a000000 | (0x11 << 11) | (0x40); 98 | out32(addr, in32(addr) & ~0x1); 99 | addr = 0x1a000000 | (0x11 << 11) | (0x8); 100 | printk("SATA Class Code: %08x\r\n", in32(addr)); 101 | 102 | addr = 0x1a000000 | (0x11 << 11) | (0x24); 103 | uint32_t bar5 = in32(addr); 104 | printk("SATA BAR5 = %08x\r\n", bar5); 105 | printk("SATA CAP = %08x\r\n", in32(bar5)); 106 | printk("SATA GHC = %08x\r\n", in32(bar5 + 4)); 107 | 108 | for (i = 0; i < 4; ++i) { 109 | addr = 0x1a000000 | (0x11 << 11) | (0x10 + 4 * i); 110 | bar = in32(addr) | 0x18000000; 111 | bar &= ~0x7; 112 | for (j = 0; j <= 1; ++j) { 113 | out8(bar + 0x6, 0xe0 + (j << 4)); 114 | usleep(1000); 115 | stat = in8(bar + 0x7); 116 | printk("IDE DEV %d:%d STAT %02x\r\n", i, j, stat); 117 | if ((stat & 0x40) && !(stat & 0x21)) { 118 | port = i; 119 | slave = j; 120 | } 121 | } 122 | } 123 | 124 | printk("Port, Slave = %d, %d\r\n", port, slave); 125 | 126 | out32(0xefdfb0000f0, 0); 127 | out32(0xefdfb0000f8, 0); 128 | 129 | printk("Setting up HT interrupts\r\n"); 130 | 131 | #define IO_REGS_BASE 0x3ff00000 132 | out8(0x3ff0140a, 0x11); /* LPC to core 0 int 0 */ 133 | for (addr = 0x3ff01418; addr <= 0x3ff0141f; ++addr) 134 | out8(addr, 0x21); /* HT1 to core 0 int 1 */ 135 | 136 | /* 137 | for (addr64 = 0xefdfb0000a0; addr64 <= 0xefdfb0000bc; addr64 += 4) 138 | out32(addr, 0xffffffff); 139 | */ 140 | out32(0xefdfb0000a0, 0xffffffff); 141 | uint32_t inten = in32(0x3ff01424); 142 | out32(0x3ff01428, inten | (0xffff << 16) | (1 << 10)); 143 | 144 | /* Setting up i8259A interrupts */ 145 | out8(0x18000021, 0xff); /* PIC_MASTER_IMR */ 146 | out8(0x180000a1, 0xff); /* PIC_SLAVE_IMR */ 147 | out8(0x18000020, 0x11); /* PIC_MASTER_CMD */ 148 | out8(0x18000080, 0); 149 | out8(0x18000080, 0); 150 | out8(0x18000080, 0); 151 | out8(0x18000080, 0); 152 | out8(0x18000021, 0); /* T_IRQ0 */ 153 | out8(0x18000080, 0); 154 | out8(0x18000080, 0); 155 | out8(0x18000080, 0); 156 | out8(0x18000080, 0); 157 | out8(0x18000021, 1 << 2); /* PIC_CASCADE_IR */ 158 | out8(0x18000080, 0); 159 | out8(0x18000080, 0); 160 | out8(0x18000080, 0); 161 | out8(0x18000080, 0); 162 | out8(0x18000021, 0x1); /* Normal EOI as Linux/MIPS */ 163 | out8(0x18000080, 0); 164 | out8(0x18000080, 0); 165 | out8(0x18000080, 0); 166 | out8(0x18000080, 0); 167 | out8(0x180000a0, 0x11); /* PIC_SLAVE_CMD */ 168 | out8(0x18000080, 0); 169 | out8(0x18000080, 0); 170 | out8(0x18000080, 0); 171 | out8(0x18000080, 0); 172 | out8(0x180000a1, 8); /* T_IRQ0 + 8 */ 173 | out8(0x18000080, 0); 174 | out8(0x18000080, 0); 175 | out8(0x18000080, 0); 176 | out8(0x18000080, 0); 177 | out8(0x180000a1, 2); 178 | out8(0x18000080, 0); 179 | out8(0x18000080, 0); 180 | out8(0x18000080, 0); 181 | out8(0x18000080, 0); 182 | out8(0x180000a1, 0x1); /* ditto */ 183 | out8(0x18000080, 0); 184 | out8(0x18000080, 0); 185 | out8(0x18000080, 0); 186 | out8(0x18000080, 0); 187 | usleep(100); 188 | /* Enable all i8259A interrupts */ 189 | out8(0x18000021, 0x00); 190 | out8(0x180000a1, 0x00); 191 | /* Read 1st sector */ 192 | uint32_t cause = read_c0_cause(); 193 | printk("CAUSE BEFORE: %08x\r\n", cause); 194 | out8(0x18000020, 0x0a); 195 | out8(0x180000a0, 0x0a); 196 | printk("IRR_MASTER: %02x\r\n", in8(0x18000020)); 197 | printk("IRR_SLAVE: %02x\r\n", in8(0x180000a0)); 198 | out8(0x18000020, 0x0b); 199 | out8(0x180000a0, 0x0b); 200 | printk("ISR_MASTER: %02x\r\n", in8(0x18000020)); 201 | printk("ISR_SLAVE: %02x\r\n", in8(0x180000a0)); 202 | printk("IMR_MASTER: %02x\r\n", in8(0x18000021)); 203 | printk("IMR_SLAVE: %02x\r\n", in8(0x180000a1)); 204 | out32(bar5 + 4, 0x2); 205 | printk("BAR5 GHC: %08x\r\n", in32(bar5 + 4)); 206 | addr = 0x1a000000 | (0x11 << 11) | 0; 207 | printk("DEV ID: %08x\r\n", in32(addr)); 208 | addr = 0x1a000000 | (0x11 << 11) | 0x4; 209 | printk("DEV CMD: %08x\r\n", in32(addr)); 210 | addr = 0x1a000000 | (0x11 << 11) | (0x10 + 4 * (port + 4)); 211 | uint32_t bar4 = in32(addr) | 0x18000000; 212 | bar4 &= ~0xf; 213 | printk("BUS-MASTER STATUS: %02x\r\n", in8(bar4 + 0x2)); 214 | printk("BUS-MASTER STATUS: %02x\r\n", in8(bar4 + 0xa)); 215 | addr = 0x1a000000 | (0x11 << 11) | (0x10 + 4 * port); 216 | bar = in32(addr) | 0x18000000; 217 | bar &= ~0x7; 218 | addr = 0x1a000000 | (0x11 << 11) | (0x10 + 4 * (port + 1)); 219 | uint32_t bar_ctrl = in32(addr) | 0x18000000; 220 | bar_ctrl &= ~0x3; 221 | printk("Reading 1st sector...\r\n"); 222 | out8(bar + 0x2, 1); 223 | out8(bar + 0x3, 0); 224 | out8(bar + 0x4, 0); 225 | out8(bar + 0x5, 0); 226 | out8(bar + 0x6, 0xe0 + (slave << 4)); 227 | out8(bar_ctrl + 0x2, 0x0); /* Interrupt */ 228 | out8(bar + 0x7, /*0xec*/0x20); 229 | /* It's expected that the two CAUSE register values should be different 230 | * indicating that an interrupt visible to the processor happened. 231 | * Not working now, though. */ 232 | while (cause == read_c0_cause()) { 233 | /* nothing */; 234 | out8(0x18000020, 0x0a); 235 | out8(0x180000a0, 0x0a); 236 | printk("IRR_MASTER: %02x\r\n", in8(0x18000020)); 237 | printk("IRR_SLAVE: %02x\r\n", in8(0x180000a0)); 238 | out8(0x18000020, 0x0b); 239 | out8(0x180000a0, 0x0b); 240 | printk("ISR_MASTER: %02x\r\n", in8(0x18000020)); 241 | printk("ISR_SLAVE: %02x\r\n", in8(0x180000a0)); 242 | printk("IMR_MASTER: %02x\r\n", in8(0x18000021)); 243 | printk("IMR_SLAVE: %02x\r\n", in8(0x180000a1)); 244 | printk("BUS-MASTER STATUS: %02x\r\n", in8(bar4 + 0x2)); 245 | printk("BUS-MASTER STATUS: %02x\r\n", in8(bar4 + 0xa)); 246 | addr = 0x1a000000 | (0x11 << 11) | 0x4; 247 | printk("DEV CMD: %08x\r\n", in32(addr)); 248 | usleep(2000000); 249 | } 250 | printk("CAUSE AFTER: %08x\r\n", read_c0_cause()); 251 | if ((stat = in8(bar + 0x7)) & 0x01) { 252 | printk("ERROR?\r\n"); 253 | return; 254 | } 255 | uint8_t buf, buf2; 256 | int cnt = 1; 257 | while (in8(bar + 0x7) & 0x08) { 258 | buf = in8(bar); 259 | buf2 = in8(bar); 260 | printk("%02x %02x%s", buf, buf2, cnt % 8 == 0 ? "\r\n" : " "); 261 | ++cnt; 262 | usleep(1); 263 | if (cnt == 1000) { 264 | printk("Exceeds\r\n"); 265 | break; 266 | } 267 | } 268 | printk("Finished\r\n"); 269 | } 270 | 271 | -------------------------------------------------------------------------------- /tools/stab/readstab.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Gan Quan 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "include/stab.h" 23 | 24 | unsigned char typecodes[] = { 25 | N_GSYM, N_FNAME, N_FUN, N_STSYM, N_LCSYM, N_MAIN, N_PC, N_RSYM, 26 | N_SLINE, N_DSLINE, N_BSLINE, N_SSYM, N_SO, N_LSYM, N_BINCL, 27 | N_SOL, N_PSYM, N_EINCL, N_ENTRY, N_LBRAC, N_EXCL, N_RBRAC, 28 | N_BCOMM, N_ECOMM, N_ECOML, N_LENG 29 | }; 30 | 31 | const char *types[256] = { 32 | [N_GSYM] = "global symbol", 33 | [N_FNAME] = "f77 func", 34 | [N_FUN] = "func", 35 | [N_STSYM] = "data segment var", 36 | [N_LCSYM] = "bss segment var", 37 | [N_MAIN] = "main func", 38 | [N_PC] = "global Pascal symbol", 39 | [N_RSYM] = "register var", 40 | [N_SLINE] = "text line #", 41 | [N_DSLINE] = "data line #", 42 | [N_BSLINE] = "bss line #", 43 | [N_SSYM] = "struct/union element", 44 | [N_SO] = "source file", 45 | [N_LSYM] = "local var", 46 | [N_BINCL] = "include begin", 47 | [N_SOL] = "include source file", 48 | [N_PSYM] = "argument var", 49 | [N_EINCL] = "include end", 50 | [N_ENTRY] = "alt. entry", 51 | [N_LBRAC] = "left brace", 52 | [N_EXCL] = "deleted include", 53 | [N_RBRAC] = "right brace", 54 | [N_BCOMM] = "common begin", 55 | [N_ECOMM] = "common end", 56 | [N_ECOML] = "common end local", 57 | [N_LENG] = "length" 58 | }; 59 | 60 | #define NR_ELEMENTS(arr) (sizeof(arr) / sizeof(arr[0])) 61 | 62 | #define STABSTR ".stabstr" 63 | #define STABS ".stabs" 64 | 65 | unsigned int elf32, elf_little_endian; 66 | 67 | inline uint16_t htofs(uint16_t hostbits) 68 | { 69 | return elf_little_endian ? htole16(hostbits) : htobe16(hostbits); 70 | } 71 | 72 | inline uint32_t htofl(uint32_t hostbits) 73 | { 74 | return elf_little_endian ? htole32(hostbits) : htobe32(hostbits); 75 | } 76 | 77 | inline uint64_t htofx(uint64_t hostbits) 78 | { 79 | return elf_little_endian ? htole64(hostbits) : htobe64(hostbits); 80 | } 81 | 82 | inline uint16_t ftohs(uint16_t hostbits) 83 | { 84 | return elf_little_endian ? le16toh(hostbits) : be16toh(hostbits); 85 | } 86 | 87 | inline uint32_t ftohl(uint32_t hostbits) 88 | { 89 | return elf_little_endian ? le32toh(hostbits) : be32toh(hostbits); 90 | } 91 | 92 | inline uint64_t ftohx(uint64_t hostbits) 93 | { 94 | return elf_little_endian ? le64toh(hostbits) : be64toh(hostbits); 95 | } 96 | 97 | void usage(char *prog) 98 | { 99 | printf("Usage: %s \n", prog); 100 | exit(1); 101 | } 102 | 103 | void readstab64(int fd, Elf64_Ehdr *eh64) 104 | { 105 | Elf64_Shdr es64, es64_stab; 106 | unsigned int i; 107 | char *shstrtab = NULL, *stabstr = NULL; 108 | struct stab stab; 109 | off_t cur; 110 | 111 | if (lseek(fd, eh64->e_shoff, SEEK_SET) == -1) 112 | err(4, "lseek"); 113 | /* Locate section header string table (.shstrtab) first */ 114 | if (lseek(fd, eh64->e_shentsize * eh64->e_shstrndx, SEEK_CUR) == -1) 115 | err(4, "lseek"); 116 | if (read(fd, &es64, sizeof(es64)) == -1) 117 | err(4, "read"); 118 | if ((shstrtab = (char *)malloc(es64.sh_size)) == NULL) 119 | err(4, "malloc"); 120 | if (lseek(fd, es64.sh_offset, SEEK_SET) == -1) 121 | err(4, "lseek"); 122 | if (read(fd, shstrtab, es64.sh_size) == -1) 123 | err(4, "read"); 124 | /* Relocate to the start of section header table */ 125 | if (lseek(fd, eh64->e_shoff, SEEK_SET) == -1) 126 | err(4, "lseek"); 127 | 128 | /* Load the stab string section */ 129 | for (i = 0; i < eh64->e_shnum; ++i) { 130 | if (read(fd, &es64, sizeof(es64)) == -1) 131 | err(4, "read"); 132 | if ((cur = lseek(fd, 0, SEEK_CUR)) == -1) 133 | err(4, "lseek"); 134 | if (strcmp(shstrtab + es64.sh_name, STABSTR) == 0) { 135 | if ((stabstr = (char *)malloc(es64.sh_size)) == NULL) 136 | err(4, "malloc"); 137 | if (lseek(fd, es64.sh_offset, SEEK_SET) == -1) 138 | err(4, "lseek"); 139 | if (read(fd, stabstr, es64.sh_size) == -1) 140 | err(4, "read"); 141 | } else if (strcmp(shstrtab + es64.sh_name, STABS) == 0) { 142 | memcpy(&es64_stab, &es64, sizeof(es64)); 143 | } 144 | if (lseek(fd, cur, SEEK_SET) == -1) 145 | err(4, "lseek"); 146 | } 147 | 148 | if (stabstr == NULL) 149 | err(8, "No stab string section found"); 150 | 151 | printf("%-20s %-8s %-8s %-8s %s\n", 152 | "Type", "Desc", "Other", "Value", "Name"); 153 | 154 | /* Locate the stab section */ 155 | if (lseek(fd, es64_stab.sh_offset, SEEK_SET) == -1) 156 | err(4, "lseek"); 157 | for (i = 0; i < es64_stab.sh_size / sizeof(stab); ++i) { 158 | read(fd, &stab, sizeof(stab)); 159 | printf("%-20s %-8d %-8d %08x %s\n", 160 | types[stab.n_type], stab.n_desc, stab.n_other, 161 | stab.n_value, stabstr + stab.n_strx); 162 | } 163 | 164 | free(shstrtab); 165 | free(stabstr); 166 | } 167 | 168 | void readstab32(int fd, Elf32_Ehdr *eh32) 169 | { 170 | Elf32_Shdr es32, es32_stab; 171 | unsigned int i; 172 | char *shstrtab = NULL, *stabstr = NULL; 173 | struct stab stab; 174 | 175 | if (lseek(fd, eh32->e_shoff, SEEK_SET) == -1) 176 | err(4, "lseek"); 177 | /* Locate section header string table (.shstrtab) first */ 178 | if (lseek(fd, eh32->e_shentsize * eh32->e_shstrndx, SEEK_CUR) == -1) 179 | err(4, "lseek"); 180 | if (read(fd, &es32, sizeof(es32)) == -1) 181 | err(4, "read"); 182 | if ((shstrtab = (char *)malloc(es32.sh_size)) == NULL) 183 | err(4, "malloc"); 184 | if (lseek(fd, es32.sh_offset, SEEK_SET) == -1) 185 | err(4, "lseek"); 186 | if (read(fd, shstrtab, es32.sh_size) == -1) 187 | err(4, "read"); 188 | /* Relocate to the start of section header table */ 189 | if (lseek(fd, eh32->e_shoff, SEEK_SET) == -1) 190 | err(4, "lseek"); 191 | 192 | /* Load the stab string section */ 193 | for (i = 0; i < eh32->e_shnum; ++i) { 194 | if (read(fd, &es32, sizeof(es32)) == -1) 195 | err(4, "read"); 196 | if (strcmp(shstrtab + es32.sh_name, STABSTR) == 0) { 197 | if ((stabstr = (char *)malloc(es32.sh_size)) == NULL) 198 | err(4, "malloc"); 199 | if (lseek(fd, es32.sh_offset, SEEK_SET) == -1) 200 | err(4, "lseek"); 201 | if (read(fd, stabstr, es32.sh_size) == -1) 202 | err(4, "read"); 203 | } else if (strcmp(shstrtab + es32.sh_name, STABS) == 0) { 204 | memcpy(&es32_stab, &es32, sizeof(es32)); 205 | } 206 | } 207 | 208 | if (stabstr == NULL) 209 | err(8, "No stab string section found"); 210 | 211 | printf("%-20s %-8s %-8s %-8s %s\n", 212 | "Type", "Desc", "Other", "Value", "Name"); 213 | 214 | /* Locate the stab section */ 215 | if (lseek(fd, es32.sh_offset, SEEK_SET) == -1) 216 | err(4, "lseek"); 217 | for (i = 0; i < es32.sh_size / sizeof(stab); ++i) { 218 | read(fd, &stab, sizeof(stab)); 219 | printf("%-20s %-8d %-8d %08x %s\n", 220 | types[stab.n_type], stab.n_desc, stab.n_other, 221 | stab.n_value, stabstr + stab.n_strx); 222 | } 223 | 224 | free(shstrtab); 225 | free(stabstr); 226 | } 227 | 228 | void readstab(char *fname) 229 | { 230 | int fd; 231 | union { 232 | Elf32_Ehdr eh32; 233 | Elf64_Ehdr eh64; 234 | } eh; 235 | off_t stab, stabstr; 236 | size_t stab_size, stabstr_size; 237 | 238 | if ((fd = open(fname, O_RDONLY)) == -1) 239 | err(2, "open"); 240 | 241 | if (read(fd, &eh, sizeof(eh)) == -1) 242 | err(4, "read"); 243 | 244 | if (strncmp(eh.eh32.e_ident, ELFMAG, SELFMAG) != 0) 245 | errx(8, "%s: not a valid ELF file\n", fname); 246 | 247 | switch (eh.eh32.e_ident[EI_CLASS]) { 248 | case ELFCLASS32: 249 | lseek(fd, sizeof(eh.eh32), SEEK_SET); 250 | elf32 = 1; 251 | break; 252 | case ELFCLASS64: 253 | lseek(fd, sizeof(eh.eh64), SEEK_SET); 254 | elf32 = 0; 255 | break; 256 | default: 257 | errx(8, "%s: unknown ELF class\n", fname); 258 | break; 259 | } 260 | 261 | switch (eh.eh32.e_ident[EI_DATA]) { 262 | case ELFDATA2LSB: 263 | elf_little_endian = 1; 264 | break; 265 | case ELFDATA2MSB: 266 | elf_little_endian = 0; 267 | break; 268 | default: 269 | errx(8, "%s: unknown data encoding\n", fname); 270 | break; 271 | } 272 | 273 | if (elf32) 274 | readstab32(fd, &eh.eh32); 275 | else 276 | readstab64(fd, &eh.eh64); 277 | 278 | close(fd); 279 | } 280 | 281 | int main(int argc, char *argv[]) 282 | { 283 | if (argc != 2) 284 | usage(argv[0]); 285 | 286 | readstab(argv[1]); 287 | 288 | return 0; 289 | } 290 | -------------------------------------------------------------------------------- /drivers/sd/sd-zynq7000.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 David Gao 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the GNU General Public License as published by the 6 | * Free Software Foundation; either version 2 of the License, or (at your 7 | * option) any later version. 8 | * 9 | */ 10 | 11 | #ifndef _DRIVERS_SD_SD_ZYNQ7000_H 12 | #define _DRIVERS_SD_SD_ZYNQ7000_H 13 | 14 | /* 15 | * ZYNQ7000 SD driver 16 | */ 17 | 18 | #include 19 | 20 | #ifdef KERNEL 21 | #define SD_BASE sd0_base 22 | #else /* KERNEL */ 23 | #define SD_BASE SD0_PHYSBASE 24 | #endif /* KERNEL */ 25 | 26 | void sd_init(); 27 | int sd_spin_init_mem_card(); 28 | int sd_dma_spin_read(u32 pa, u16 count, u32 offset); 29 | int sd_dma_spin_write(u32 pa, u16 count, u32 offset); 30 | int sd_spin_send_cmd(u16 cmd, u16 count, u32 arg, int mode); 31 | 32 | /* Register Offset */ 33 | #define SD_SDMA_SYS_ADDR_OFFSET 0x00 /* u32 */ 34 | #define SD_BLK_SIZE_OFFSET 0x04 /* u16 */ 35 | #define SD_BLK_CNT_OFFSET 0x06 /* u16 */ 36 | #define SD_ARGMT_OFFSET 0x08 /* u32 */ 37 | #define SD_XFER_MODE_OFFSET 0x0C /* u16 */ 38 | #define SD_CMD_OFFSET 0x0E /* u16 */ 39 | #define SD_RESP0_OFFSET 0x10 /* u32 */ 40 | #define SD_RESP1_OFFSET 0x14 /* u32 */ 41 | #define SD_RESP2_OFFSET 0x18 /* u32 */ 42 | #define SD_RESP3_OFFSET 0x1C /* u32 */ 43 | #define SD_BUF_DAT_PORT_OFFSET 0x20 /* u32 */ 44 | #define SD_PRES_STATE_OFFSET 0x24 /* u32 */ 45 | #define SD_HOST_CTRL1_OFFSET 0x28 /* u8 */ 46 | #define SD_POWER_CTRL_OFFSET 0x29 /* u8 */ 47 | #define SD_BLK_GAP_CTRL_OFFSET 0x2A /* u8 */ 48 | #define SD_WAKE_UP_CTRL_OFFSET 0x2B /* u8 */ 49 | #define SD_CLK_CTRL_OFFSET 0x2C /* u16 */ 50 | #define SD_TIMEOUT_CTRL_OFFSET 0x2E /* u8 */ 51 | #define SD_SW_RST_OFFSET 0x2F /* u8 */ 52 | #define SD_NORM_INTR_STS_OFFSET 0x30 /* u16 */ 53 | #define SD_ERR_INTR_STS_OFFSET 0x32 /* u16 */ 54 | #define SD_NORM_INTR_STS_EN_OFFSET 0x34 /* u16 */ 55 | #define SD_ERR_INTR_STS_EN_OFFSET 0x36 /* u16 */ 56 | #define SD_NORM_INTR_SIG_EN_OFFSET 0x38 /* u16 */ 57 | #define SD_ERR_INTR_SIG_EN_OFFSET 0x3A /* u16 */ 58 | #define SD_AUTO_CMD12_ERR_STS_OFFSET 0x3C /* u16 */ 59 | #define SD_HOST_CTRL2_OFFSET 0x3E /* u16 */ 60 | #define SD_CAPS_OFFSET 0x40 /* u32 */ 61 | #define SD_CAPS_EXT_OFFSET 0x44 /* u32 */ 62 | #define SD_MAX_CURR_CAPS_OFFSET 0x48 /* u32 */ 63 | #define SD_MAX_CURR_CAPS_EXT_OFFSET 0x4C /* u32 */ 64 | #define SD_FE_AUTO_CMD12_EIS_OFFSET 0x50 /* u16 */ 65 | #define SD_FE_ERR_INT_STS_OFFSET 0x52 /* u16 */ 66 | #define SD_ADMA_ERR_STS_OFFSET 0x54 /* u32 */ 67 | #define SD_ADMA_SAR_OFFSET 0x58 /* u32 */ 68 | #define SD_ADMA_SAR_EXT_OFFSET 0x5C /* u32 */ 69 | #define SD_PRE_VAL_1_OFFSET 0x60 /* u32 */ 70 | #define SD_PRE_VAL_2_OFFSET 0x64 /* u32 */ 71 | #define SD_PRE_VAL_13_OFFSET 0x68 /* u32 */ 72 | #define SD_PRE_VAL_4_OFFSET 0x6C /* u32 */ 73 | #define SD_SHARED_BUS_CTRL_OFFSET 0xE0 /* u32 */ 74 | #define SD_SLOT_INTR_STS_OFFSET 0xFC /* u32 */ 75 | #define SD_HOST_CTRL_VER_OFFSET 0xFE /* u32 */ 76 | 77 | /* Block Size */ 78 | #define SD_BLK_SIZE_MASK 0x0FFF 79 | #define SD_SDMA_BUFF_SIZE_MASK 0x7000 80 | 81 | /* Transfer Mode */ 82 | #define SD_TM_MUL_SIN_BLK_SEL 0x20 83 | #define SD_TM_DAT_DIR_SEL 0x10 84 | #define SD_TM_AUTO_CMD12_EN 0x04 85 | #define SD_TM_BLK_CNT_EN 0x02 86 | #define SD_TM_DMA_EN 0x01 87 | 88 | /* Present State */ 89 | #define SD_PSR_WPS_PL 0x00080000 90 | #define SD_PSR_CARD_DPL 0x00040000 91 | #define SD_PSR_CARD_STABLE 0x00020000 92 | #define SD_PSR_CARD_INSRT 0x00010000 93 | #define SD_PSR_BUFF_RD_EN 0x00000800 94 | #define SD_PSR_BUFF_WR_EN 0x00000400 95 | #define SD_PSR_RD_ACTIVE 0x00000200 96 | #define SD_PSR_WR_ACTIVE 0x00000100 97 | #define SD_PSR_DAT_ACTIVE 0x00000004 98 | #define SD_PSR_INHIBIT_DAT 0x00000002 99 | #define SD_PSR_INHIBIT_CMD 0x00000001 100 | 101 | /* Host Controls */ 102 | #define SD_HC_CARD_DET_SD 0x80 103 | #define SD_HC_CARD_DET_TL 0x40 104 | #define SD_HC_EXT_BUS_WIDTH 0x20 105 | #define SD_HC_DMA_MASK 0x18 106 | #define SD_HC_DMA_ADMA2_64 0x18 107 | #define SD_HC_DMA_ADMA2_32 0x10 108 | #define SD_HC_DMA_ADMA1 0x08 109 | #define SD_HC_SPEED 0x04 110 | #define SD_HC_WIDTH 0x02 111 | #define SD_HC_LED 0x01 112 | #define SD_HC_DMA_SDMA 0x00 113 | 114 | /* Power control */ 115 | #define SD_PC_BUS_VSEL_MASK 0x0E 116 | #define SD_PC_BUS_VSEL_3V3 0x0E 117 | #define SD_PC_BUS_VSEL_3V0 0x0C 118 | #define SD_PC_BUS_VSEL_1V8 0x0A 119 | #define SD_PC_BUS_PWR 0x01 120 | 121 | /* Block Gap Control */ 122 | #define SD_BGC_BOOT_ACK 0x80 123 | #define SD_BGC_ALT_BOOT_EN 0x40 124 | #define SD_BGC_BOOT_EN 0x20 125 | #define SD_BGC_SPI_MODE 0x10 126 | #define SD_BGC_INTR 0x08 127 | #define SD_BGC_RWC 0x04 128 | #define SD_BGC_CNT_REQ 0x02 129 | #define SD_BGC_STP_REQ 0x01 130 | 131 | /* Wake Up Control */ 132 | #define SD_WC_WUP_ON_REM 0x04 133 | #define SD_WC_WUP_ON_INSRT 0x02 134 | #define SD_WC_WUP_ON_INTR 0x01 135 | 136 | /* Clock Control */ 137 | #define SD_CC_SDCLK_FREQ_MASK 0xFF00 138 | #define SD_CC_SDCLK_FREQ_D256 0x8000 139 | #define SD_CC_SDCLK_FREQ_D128 0x4000 140 | #define SD_CC_SDCLK_FREQ_D64 0x2000 141 | #define SD_CC_SDCLK_FREQ_D32 0x1000 142 | #define SD_CC_SDCLK_FREQ_D16 0x0800 143 | #define SD_CC_SDCLK_FREQ_D8 0x0400 144 | #define SD_CC_SDCLK_FREQ_D4 0x0200 145 | #define SD_CC_SDCLK_FREQ_D2 0x0100 146 | #define SD_CC_SDCLK_FREQ_BASE 0x0000 147 | #define SD_CC_SDCLK_FREQ_EXT_MASK 0x00C0 148 | #define SD_CC_SD_CLK_GEN_SEL 0x0020 149 | #define SD_CC_SD_CLK_EN 0x0004 150 | #define SD_CC_INT_CLK_STABLE 0x0002 151 | #define SD_CC_INT_CLK_EN 0x0001 152 | #define SD_CC_MAX_NUM_OF_DIV 9 153 | #define SD_CC_DIV_SHIFT 8 154 | 155 | /* Timeout Control */ 156 | #define SD_TC_CNTR_VAL_MASK 0x0000000F 157 | 158 | /* Reset */ 159 | #define SD_SWRST_ALL_MASK 0x00000001 160 | #define SD_SWRST_CMD_LINE_MASK 0x00000002 161 | #define SD_SWRST_DAT_LINE_MASK 0x00000004 162 | 163 | /* Normal Interrupt */ 164 | #define SD_NORM_INTR_ALL 0xFFFF 165 | #define SD_INTR_ERR 0x8000 166 | #define SD_INTR_BOOT_ACK_RECV 0x4000 167 | #define SD_INTR_BOOT_TERM 0x2000 168 | #define SD_INTR_RE_TUNING 0x1000 169 | #define SD_INTR_INT_C 0x0800 170 | #define SD_INTR_INT_B 0x0400 171 | #define SD_INTR_INT_A 0x0200 172 | #define SD_INTR_CARD 0x0100 173 | #define SD_INTR_CARD_REM 0x0080 174 | #define SD_INTR_CARD_INSRT 0x0040 175 | #define SD_INTR_BRR 0x0020 176 | #define SD_INTR_BWR 0x0010 177 | #define SD_INTR_DMA 0x0008 178 | #define SD_INTR_BGE 0x0004 179 | #define SD_INTR_TC 0x0002 180 | #define SD_INTR_CC 0x0001 181 | 182 | /* Error Interrupts */ 183 | #define SD_ERR_INTR_ALL 0xF3FF 184 | #define SD_INTR_VEND_SPF_ERR 0xE000 185 | #define SD_INTR_ERR_TR 0x1000 186 | #define SD_INTR_ERR_ADMA 0x0200 187 | #define SD_INTR_ERR_AUTO_CMD12 0x0100 188 | #define SD_INTR_ERR_I_LMT 0x0080 189 | #define SD_INTR_ERR_DEB 0x0040 190 | #define SD_INTR_ERR_DCRC 0x0020 191 | #define SD_INTR_ERR_DT 0x0010 192 | #define SD_INTR_ERR_CI 0x0008 193 | #define SD_INTR_ERR_CEB 0x0004 194 | #define SD_INTR_ERR_CCRC 0x0002 195 | #define SD_INTR_ERR_CT 0x0001 196 | 197 | /* Command and response */ 198 | #define SD_CMD_TYPE_MASK 0xC0 199 | #define SD_CMD_TYPE_ABORT 0xC0 200 | #define SD_CMD_TYPE_RESUME 0x80 201 | #define SD_CMD_TYPE_SUSPEND 0x40 202 | #define SD_DAT_PRESENT 0x20 203 | #define SD_CMD_INX_CHK_EN 0x10 204 | #define SD_CMD_CRC_CHK_EN 0x08 205 | #define SD_CMD_TYPE_NORM 0x00 206 | #define SD_CMD_RESP_MASK 0x03 207 | #define SD_CMD_RESP_L48_BSY_CHK 0x03 208 | #define SD_CMD_RESP_L48 0x02 209 | #define SD_CMD_RESP_L136 0x01 210 | #define SD_CMD_RESP_NONE 0x00 211 | 212 | /* Command */ 213 | #define SD_CMD_MASK 0x3F00 214 | #define SD_CMD0 0x0000 215 | #define SD_CMD1 0x0100 216 | #define SD_CMD2 0x0200 217 | #define SD_CMD3 0x0300 218 | #define SD_CMD4 0x0400 219 | #define SD_CMD5 0x0500 220 | #define SD_CMD6 0x0600 221 | #define SD_CMD7 0x0700 222 | #define SD_CMD8 0x0800 223 | #define SD_CMD9 0x0900 224 | #define SD_CMD10 0x0A00 225 | #define SD_CMD12 0x0C00 226 | #define SD_CMD16 0x1000 227 | #define SD_CMD17 0x1100 228 | #define SD_CMD18 0x1200 229 | #define SD_CMD23 0x1700 230 | #define SD_CMD24 0x1800 231 | #define SD_CMD25 0x1900 232 | #define SD_CMD41 0x2900 233 | #define SD_CMD52 0x3400 234 | #define SD_CMD55 0x3700 235 | #define SD_CMD58 0x3A00 236 | #define SD_ACMD6 0x8600 237 | #define SD_ACMD13 0x8D00 238 | #define SD_ACMD23 0x9700 239 | #define SD_ACMD41 0xA900 240 | #define SD_ACMD42 0xAA00 241 | #define SD_ACMD51 0xB300 242 | 243 | /* Response */ 244 | #define SD_RESP_NONE SD_CMD_RESP_NONE 245 | #define SD_RESP_R1 (SD_CMD_RESP_L48 | SD_CMD_CRC_CHK_EN | SD_CMD_INX_CHK_EN) 246 | #define SD_RESP_R1B (SD_CMD_RESP_L48_BSY_CHK | SD_CMD_CRC_CHK_EN | SD_CMD_INX_CHK_EN) 247 | #define SD_RESP_R2 (SD_CMD_RESP_L136 | SD_CMD_CRC_CHK_EN) 248 | #define SD_RESP_R3 (SD_CMD_RESP_L48) 249 | #define SD_RESP_R6 (SD_CMD_RESP_L48_BSY_CHK | SD_CMD_CRC_CHK_EN | SD_CMD_INX_CHK_EN) 250 | 251 | /* Capabilities */ 252 | #define SD_CAP_SPI_MODE 0x20000000 253 | #define SD_CAP_SPI_BLOCK_MODE 0x20000000 254 | #define SD_CAP_SYS_BUS_64 0x10000000 255 | #define SD_CAP_INTR_MODE 0x08000000 256 | #define SD_CAP_VOLT_1V8 0x04000000 257 | #define SD_CAP_VOLT_3V0 0x02000000 258 | #define SD_CAP_VOLT_3V3 0x01000000 259 | #define SD_CAP_SUSP_RESUME 0x00800000 260 | #define SD_CAP_SDMA 0x00400000 261 | #define SD_CAP_HIGH_SPEED 0x00200000 262 | #define SD_CAP_ADMA2 0x00080000 263 | #define SD_CAP_EXT_MEDIA_BUS 0x00040000 264 | #define SD_CAP_MAX_BLK_LEN_MASK 0x00030000 265 | #define SD_CAP_TOUT_CLK_UNIT 0x00000080 266 | #define SD_CAP_TOUT_CLK_FREQ 0x0000003F 267 | #define SD_CAP_MAX_BLK_LEN_512B 0x00000000 268 | 269 | /* ADMA2 Descripter*/ 270 | #define SD_DESC_MAX_LENGTH 65536 271 | 272 | #define SD_DESC_VALID 0x01 273 | #define SD_DESC_END 0x02 274 | #define SD_DESC_INT 0x04 275 | #define SD_DESC_TRAN 0x20 276 | 277 | /* Misc */ 278 | #define SD_CMD8_VOL_PATTERN 0x01AA 279 | #define SD_RESP_READY 0x80000000 280 | #define SD_ACMD41_HCS 0x40000000 281 | #define SD_ACMD41_3V3 0x00300000 282 | #define SD_CMD1_HIGH_VOL 0x00FF8000 283 | #define SD_CMD1_DUAL_VOL 0x00FF8010 284 | 285 | #endif /* _DRIVERS_SD_SD_ZYNQ7000_H */ 286 | --------------------------------------------------------------------------------