├── .gitignore ├── .gitmodules ├── .travis.yml ├── LICENCE.GPL ├── LICENCE.broadcom ├── LICENCE.musl ├── MULTIBOOT-ARM ├── Makefile ├── Makefile.rpi-boot.in ├── README ├── assert.c ├── assert.h ├── atag.c ├── atag.h ├── bcm2709-rpi-2-b.dtb ├── block.c ├── block.h ├── block_cache.c ├── boot.s ├── boot64.s ├── config.h ├── config_parse.c ├── config_parse.h ├── console.c ├── console.h ├── crc32.c ├── crc32.h ├── ctype.c ├── ctype.h ├── dirent.h ├── dwc_usb.c ├── dwc_usb.h ├── elf.c ├── elf.h ├── emmc.c ├── errno.h ├── ext2.c ├── fat.c ├── fb.c ├── fb.h ├── font.c ├── fs.h ├── heap.c ├── libfs.c ├── linker-qemu.ld ├── linker.ld ├── log.c ├── log.h ├── main.c ├── malloc.c ├── mbox.c ├── mbox.h ├── mbr.c ├── memchunk.c ├── memchunk.h ├── mkknlimg ├── mksdimg.sh ├── mmio.c ├── mmio.h ├── multiboot.c ├── multiboot.h ├── nofs.c ├── output.c ├── output.h ├── printf.c ├── qemufw.c ├── qemufw.ld ├── ramdisk.c ├── raspbootin-server.c ├── raspbootin.c ├── raspbootin.h ├── rpi-boot-tools ├── clipLog.py └── clipLog.sh ├── rpifdt.c ├── rpifdt.h ├── stdio.c ├── stdio.h ├── stdlib.c ├── stdlib.h ├── stream.c ├── string.h ├── strstr.c ├── strtol.c ├── strtoll.c ├── test_kernel ├── Makefile ├── boot │ └── rpi-boot.cfg ├── linker.ld ├── loader.s └── main.c ├── timer.c ├── timer.h ├── uart.c ├── uart.h ├── usb.h ├── util.h ├── vfs.c └── vfs.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.elf 3 | *.img 4 | *.rpi-boot 5 | 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libdtc"] 2 | path = libdtc 3 | url = https://github.com/jncronin/dtc.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | cache: 4 | directories: 5 | - $HOME/gcc-arm-none-eabi-5_2-2015q4 6 | 7 | install: 8 | - export GCC_DIR=$HOME/gcc-arm-none-eabi-5_2-2015q4 9 | - export GCC_ARCHIVE=$HOME/gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 10 | - export GCC_URL=https://launchpad.net/gcc-arm-embedded/5.0/5-2015-q4-major/+download/gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 11 | - if [ ! -e $GCC_DIR/bin/arm-none-eabi-g++ ]; then wget $GCC_URL -O $GCC_ARCHIVE; tar xfj $GCC_ARCHIVE -C $HOME; fi 12 | - export PATH=$PATH:$GCC_DIR/bin 13 | - export CROSS_COMPILE=$GCC_DIR/bin/arm-none-eabi- 14 | 15 | script: make 16 | 17 | 18 | -------------------------------------------------------------------------------- /LICENCE.broadcom: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006, Broadcom Corporation. 2 | Copyright (c) 2015, Raspberry Pi (Trading) Ltd 3 | All rights reserved. 4 | 5 | Redistribution. Redistribution and use in binary form, without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * This software may only be used for the purposes of developing for, 10 | running or using a Raspberry Pi device. 11 | * Redistributions must reproduce the above copyright notice and the 12 | following disclaimer in the documentation and/or other materials 13 | provided with the distribution. 14 | * Neither the name of Broadcom Corporation nor the names of its suppliers 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 19 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 20 | BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 25 | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 27 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 28 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | DAMAGE. 30 | 31 | -------------------------------------------------------------------------------- /LICENCE.musl: -------------------------------------------------------------------------------- 1 | musl as a whole is licensed under the following standard MIT license: 2 | 3 | ---------------------------------------------------------------------- 4 | Copyright © 2005-2014 Rich Felker, et al. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | ---------------------------------------------------------------------- 25 | 26 | Authors/contributors include: 27 | 28 | Alex Dowad 29 | Alexander Monakov 30 | Anthony G. Basile 31 | Arvid Picciani 32 | Bobby Bingham 33 | Boris Brezillon 34 | Brent Cook 35 | Chris Spiegel 36 | Clément Vasseur 37 | Daniel Micay 38 | Denys Vlasenko 39 | Emil Renner Berthing 40 | Felix Fietkau 41 | Felix Janda 42 | Gianluca Anzolin 43 | Hauke Mehrtens 44 | Hiltjo Posthuma 45 | Isaac Dunham 46 | Jaydeep Patil 47 | Jens Gustedt 48 | Jeremy Huntwork 49 | Jo-Philipp Wich 50 | Joakim Sindholt 51 | John Spencer 52 | Josiah Worcester 53 | Justin Cormack 54 | Khem Raj 55 | Kylie McClain 56 | Luca Barbato 57 | Luka Perkov 58 | M Farkas-Dyck (Strake) 59 | Mahesh Bodapati 60 | Michael Forney 61 | Natanael Copa 62 | Nicholas J. Kain 63 | orc 64 | Pascal Cuoq 65 | Petr Hosek 66 | Pierre Carrier 67 | Rich Felker 68 | Richard Pennington 69 | Shiz 70 | sin 71 | Solar Designer 72 | Stefan Kristiansson 73 | Szabolcs Nagy 74 | Timo Teräs 75 | Trutz Behn 76 | Valentin Ochs 77 | William Haddon 78 | 79 | Portions of this software are derived from third-party works licensed 80 | under terms compatible with the above MIT license: 81 | 82 | The TRE regular expression implementation (src/regex/reg* and 83 | src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed 84 | under a 2-clause BSD license (license text in the source files). The 85 | included version has been heavily modified by Rich Felker in 2012, in 86 | the interests of size, simplicity, and namespace cleanliness. 87 | 88 | Much of the math library code (src/math/* and src/complex/*) is 89 | Copyright © 1993,2004 Sun Microsystems or 90 | Copyright © 2003-2011 David Schultz or 91 | Copyright © 2003-2009 Steven G. Kargl or 92 | Copyright © 2003-2009 Bruce D. Evans or 93 | Copyright © 2008 Stephen L. Moshier 94 | and labelled as such in comments in the individual source files. All 95 | have been licensed under extremely permissive terms. 96 | 97 | The ARM memcpy code (src/string/arm/memcpy_el.S) is Copyright © 2008 98 | The Android Open Source Project and is licensed under a two-clause BSD 99 | license. It was taken from Bionic libc, used on Android. 100 | 101 | The implementation of DES for crypt (src/crypt/crypt_des.c) is 102 | Copyright © 1994 David Burren. It is licensed under a BSD license. 103 | 104 | The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was 105 | originally written by Solar Designer and placed into the public 106 | domain. The code also comes with a fallback permissive license for use 107 | in jurisdictions that may not recognize the public domain. 108 | 109 | The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 110 | Valentin Ochs and is licensed under an MIT-style license. 111 | 112 | The BSD PRNG implementation (src/prng/random.c) and XSI search API 113 | (src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and 114 | licensed under following terms: "Permission to use, copy, modify, 115 | and/or distribute this code for any purpose with or without fee is 116 | hereby granted. There is no warranty." 117 | 118 | The x86_64 port was written by Nicholas J. Kain and is licensed under 119 | the standard MIT terms. 120 | 121 | The mips and microblaze ports were originally written by Richard 122 | Pennington for use in the ellcc project. The original code was adapted 123 | by Rich Felker for build system and code conventions during upstream 124 | integration. It is licensed under the standard MIT terms. 125 | 126 | The mips64 port was contributed by Imagination Technologies and is 127 | licensed under the standard MIT terms. 128 | 129 | The powerpc port was also originally written by Richard Pennington, 130 | and later supplemented and integrated by John Spencer. It is licensed 131 | under the standard MIT terms. 132 | 133 | All other files which have no copyright comments are original works 134 | produced specifically for use as part of this library, written either 135 | by Rich Felker, the main author of the library, or by one or more 136 | contibutors listed above. Details on authorship of individual files 137 | can be found in the git version control history of the project. The 138 | omission of copyright and license comments in each file is in the 139 | interest of source tree size. 140 | 141 | In addition, permission is hereby granted for all public header files 142 | (include/* and arch/*/bits/*) and crt files intended to be linked into 143 | applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit 144 | the copyright notice and permission notice otherwise required by the 145 | license, and to use these files without any requirement of 146 | attribution. These files include substantial contributions from: 147 | 148 | Bobby Bingham 149 | John Spencer 150 | Nicholas J. Kain 151 | Rich Felker 152 | Richard Pennington 153 | Stefan Kristiansson 154 | Szabolcs Nagy 155 | 156 | all of whom have explicitly granted such permission. 157 | 158 | This file previously contained text expressing a belief that most of 159 | the files covered by the above exception were sufficiently trivial not 160 | to be subject to copyright, resulting in confusion over whether it 161 | negated the permissions granted in the license. In the spirit of 162 | permissive licensing, and of not having licensing issues being an 163 | obstacle to adoption, that text has been removed. 164 | -------------------------------------------------------------------------------- /MULTIBOOT-ARM: -------------------------------------------------------------------------------- 1 | Multiboot ARM extensions v0.1 2 | ----------------------------- 3 | 4 | This is an unofficial extension to the the Multiboot Specification version 5 | 0.6.96, available from 6 | http://www.gnu.org/software/grub/manual/multiboot/multiboot.html. 7 | 8 | It has been adapted to support booting on the ARM architecture. 9 | 10 | Please note the changes to the following sections: 11 | 12 | 3.2 Machine state 13 | ----------------- 14 | 15 | Replace all information with the following: 16 | 17 | When the boot loader invokes the 32-bit operating system, the machine must have 18 | the following state: 19 | 20 | 'R0' 21 | Must contain the magic value '0x2BADB002'; the presence of this value 22 | indicates to the operating system that it was loaded by a 23 | Multiboot-compliant boot loader (e.g. as opposed to another type of boot 24 | loader that the operating system can also be loaded from). 25 | 26 | 'R1' 27 | Must contain the 32-bit physical address of the Multiboot information 28 | provided by the boot loader (see Boot information format). 29 | 30 | 'R2' 31 | Will either contain '0' or a valid 'ARM Linux Machine Type', a list of 32 | which are maintained at http://www.arm.linux.org.uk/developer/machines/ 33 | 34 | 'R3' 35 | Will either contain '0' or a valid pointer to a table of functions 36 | provided by the boot loader for enhanced early OS functionality 37 | (see 3.2.1 ARM (rpi-boot) Bootloader functions). 38 | 39 | 'SP' 40 | There will be a valid stack provided, however its size is not 41 | guaranteed. The OS image must create its own stack as soon as 42 | possible. 43 | 44 | All other registers are undefined. 45 | 46 | In addition, the system will be running in supervisor mode with virtual 47 | memory disabled. Interrupts will be disabled. 48 | 49 | The first 1 MiB of physical memory is reserved for the bootloader. This is 50 | not reflected in the memory map provided in the multiboot header. Once the 51 | OS image has finished parsing the tables provided to it by the bootloader 52 | and is no longer using any Bootloader functions (see 3.2.1) this memory is 53 | free for use by the OS. 54 | 55 | 56 | 3.2.1 ARM (rpi-boot) Bootloader functions 57 | ----------------------------------------- 58 | 59 | This is a new section containing the following: 60 | 61 | The reference implementation of the Multiboot ARM extensions (rpi-boot) 62 | provides the OS image with functions providing functionality to 63 | enhance early OS development, particularly concerned with debugging 64 | output and loading files from the file system. 65 | 66 | If R3 on boot contains a value other than '0' then it points to a table 67 | of function pointers as defined in multiboot.h, with members defined as per 68 | POSIX. 69 | 70 | Non-POSIX functions are: 71 | 72 | void clear(): 73 | Clear the screen and reset the cursor to the top left position 74 | 75 | rpi_boot_output_state output_get_state(): 76 | Return the current state of the output subsystem (for later restoring 77 | with output_restore_state()) 78 | 79 | void output_restore_state(rpi_boot_output_state state): 80 | Restore the output state previously stored with output_get_state() 81 | 82 | void output_[enable/disable]_[method](): 83 | Enable or disable the use of a particular output method. Supported 84 | methods are: 85 | uart: output on the UART 86 | fb: framebuffer 87 | log: use the file specified by the 'console log' 88 | configuration option or register_log_file() 89 | custom: use the function specified to 90 | register_custom_output_function() 91 | 92 | int mb_arm_version(): 93 | Return the version of the multiboot arm functions structure in use by 94 | the current bootloader. Note that later structures will be backward 95 | compatible with earlier ones. 96 | 97 | long fsize(FILE *stream): 98 | Return the length of a stream. 99 | 100 | int ramdisk_init(uintptr_t address, size_t size, int fs_type, char *name): 101 | Define a ramdisk, starting at 'address', of length 'size'. The typical 102 | usage is to load a ramdisk image to memory (using fopen/fread etc) then 103 | register it with the bootloader with this function. fs_type is the type 104 | of file system to expect to find (standard partition type code as per 105 | http://www.win.tue.nl/~aeb/partitions/partition_types-1.html 106 | 'name' is the name to give the device in the bootloader e.g. if named 107 | 'ramdisk', its entries can be accessed as (ramdisk)/dir/file.txt 108 | 109 | int register_custom_output_function(int (*putc_function)(int c)): 110 | Register the putc() function to call for the 'custom' output method. 111 | 112 | int register_log_file(FILE *fp, size_t buffer_size): 113 | Register the file to output the log to if the 'log' output method is 114 | enabled. If buffer_size is > 0 it is the number of bytes to buffer 115 | before writing to the output stream. A call to fclose() will flush 116 | the buffer to the stream. 117 | 118 | FILE *get_log_file(): 119 | Return the current log file in use, for passing to fflush() for example. 120 | 121 | Path names use the '/' character as a directory delimiter. Files on a FAT 122 | filesystem are referenced by their lowercase name (in particular, looking for 123 | a file using capital letters will cause the search to fail). Paths can be 124 | prepended by a device name in round parentheses '()' to determine on which 125 | device to look for a file. e.g. to look for the file called testfile.txt 126 | in the root directory of device 'emmc0_0' the appropriate path would be: 127 | '(emmc0_0)/testfile.txt'. 128 | 129 | 130 | 3.3 Boot information format 131 | --------------------------- 132 | 133 | Please be aware of the following when reading this section: 134 | 135 | In the flags field, the following bits will never be set: 8, 10 136 | 137 | The following fields have special meaning: 138 | 139 | boot_device: 140 | This is a pointer to a null terminated string containing the name of the 141 | device from which the OS image was loaded. 142 | 143 | drives_addr: 144 | This is a pointer to a list of pointers to null terminated strings 145 | containing all the storage device names known to the bootloader. 146 | 147 | drives_length: 148 | This is the length of the above list. 149 | 150 | The additional fields (framebuffer_*) defined in multiboot.h in the grub 151 | distribution are also supported. 152 | 153 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MAKEFILE = Makefile.rpi-boot 2 | MAKEFILE_IN = $(MAKEFILE).in 3 | 4 | # Allow cross as well as native compilation 5 | CROSS_COMPILE ?= 6 | ARMCC = $(CROSS_COMPILE)gcc 7 | 8 | all: kernel.img 9 | 10 | .PHONY: clean kernel.img libfs.a qemu qemu-gdb dump kernel-qemu.elf kernel.img-atag qemufw.elf kernel-qemu.img 11 | 12 | $(MAKEFILE): $(MAKEFILE_IN) config.h Makefile 13 | $(ARMCC) -P -traditional-cpp -std=gnu99 -E -o $(MAKEFILE) -x c $(MAKEFILE_IN) $(CFLAGS) 14 | 15 | clean: $(MAKEFILE) 16 | $(MAKE) -f $(MAKEFILE) clean 17 | 18 | kernel.img: $(MAKEFILE) 19 | $(MAKE) -f $(MAKEFILE) kernel.img 20 | 21 | kernel.img-atag: $(MAKEFILE) 22 | $(MAKE) -f $(MAKEFILE) kernel.img-atag 23 | 24 | libfs.a: $(MAKEFILE) 25 | $(MAKE) -f $(MAKEFILE) libfs.a 26 | 27 | kernel-qemu.elf: $(MAKEFILE) 28 | $(MAKE) -f $(MAKEFILE) kernel-qemu.elf 29 | 30 | kernel-qemu.img: $(MAKEFILE) 31 | $(MAKE) -f $(MAKEFILE) kernel-qemu.img 32 | 33 | qemufw.elf: $(MAKEFILE) 34 | $(MAKE) -f $(MAKEFILE) qemufw.elf 35 | 36 | qemu: $(MAKEFILE) 37 | $(MAKE) -f $(MAKEFILE) qemu 38 | 39 | qemu-gdb: $(MAKEFILE) 40 | $(MAKE) -f $(MAKEFILE) qemu-gdb 41 | 42 | dump: $(MAKEFILE) 43 | $(MAKE) -f $(MAKEFILE) dump 44 | 45 | raspbootin-server: raspbootin-server.c crc32.c 46 | $(CC) -g -std=c99 -o $@ $^ 47 | -------------------------------------------------------------------------------- /Makefile.rpi-boot.in: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | /* Allow cross as well as native compilation */ 4 | CROSS_COMPILE ?= arm-none-eabi- 5 | HOSTCC = $(CC) 6 | export ARMCC ?= $(CROSS_COMPILE)gcc 7 | export ARMLD ?= $(CROSS_COMPILE)ld 8 | export ARMOBJCOPY ?= $(CROSS_COMPILE)objcopy 9 | export ARMOBJDUMP ?= $(CROSS_COMPILE)objdump 10 | export ARMAR ?= $(CROSS_COMPILE)ar 11 | 12 | QEMU ?= qemu-system-arm 13 | 14 | QEMUDTB ?= bcm2709-rpi-2-b.dtb 15 | 16 | MAKEFILE ?= Makefile.rpi-boot 17 | CONFIG_H = config.h 18 | DISASM_DUMP = kernel.list 19 | 20 | LIBFDT = libdtc/libftd/libftd.a 21 | 22 | all: kernel.img 23 | 24 | CFLAGS += -nostdlib -nostartfiles -ffreestanding -Wall -Wextra -Werror -Wshadow 25 | CFLAGS += -std=gnu99 26 | CFLAGS += -I. -Ilibdtc/libfdt 27 | CFLAGS += -DBUILDING_RPIBOOT 28 | CFLAGS += -mcpu=arm1176jzf-s 29 | CFLAGS += -mfloat-abi=soft 30 | CFLAGS += -fno-builtin 31 | CFLAGS += -fno-tree-loop-distribute-patterns 32 | 33 | ASFLAGS += -march=armv7ve 34 | ASFLAGS += -mcpu=arm1176jzf-s 35 | ASFLAGS += -mfloat-abi=soft 36 | 37 | 38 | #ifdef DEBUG 39 | CFLAGS += -g -O0 40 | ASSERT_OBJS = assert.o 41 | #else 42 | CFLAGS += -O3 43 | #endif 44 | 45 | #ifdef __aarch64__ 46 | QEMUFLAGS += -m 1G -M raspi3 -kernel kernel-qemu.img -usb -nographic 47 | CFLAGS += -mgeneral-regs-only 48 | #else 49 | QEMUFLAGS += -cpu arm1176 -m 256 -M raspi2 -kernel kernel-qemu.img -usb -nographic -dtb $(QEMUDTB) 50 | #endif 51 | SDFLAGS = -sd sd.img 52 | 53 | #ifdef ENABLE_FRAMEBUFFER 54 | FB_OBJS = fb.o console.o 55 | #endif 56 | 57 | #ifdef ENABLE_SD 58 | SD_OBJS = emmc.o 59 | #endif 60 | 61 | #ifdef ENABLE_FAT 62 | FAT_OBJS = fat.o 63 | #endif 64 | 65 | #ifdef ENABLE_EXT2 66 | EXT2_OBJS = ext2.o 67 | #endif 68 | 69 | #ifdef ENABLE_USB 70 | USB_OBJS = dwc_usb.o 71 | #endif 72 | 73 | #ifdef ENABLE_RASPBOOTIN 74 | RASPBOOTIN_OBJS = raspbootin.o 75 | #endif 76 | 77 | #ifdef ENABLE_SERIAL 78 | SERIAL_OBJS = uart.o 79 | #endif 80 | 81 | #ifdef ENABLE_DEFAULT_FONT 82 | FONT_OBJS = font.o 83 | #endif 84 | 85 | #ifdef ENABLE_RAMDISK 86 | RAMDISK_OBJS = ramdisk.o 87 | #endif 88 | 89 | #ifdef ENABLE_NOFS 90 | NOFS_OBJS = nofs.o 91 | #endif 92 | 93 | #ifdef ENABLE_BLOCK_CACHE 94 | CACHE_OBJS = block_cache.o 95 | #endif 96 | 97 | #ifdef ENABLE_CONSOLE_LOGFILE 98 | LOGFILE_OBJS = log.o 99 | #endif 100 | 101 | #ifdef HAVE_UNWIND_H 102 | #ifdef DEBUG 103 | CFLAGS += -funwind-tables 104 | #endif 105 | #endif 106 | 107 | /* Thanks to James Cone (https://github.com/JamesC1) for the idea here */ 108 | #ifdef ENABLE_ALTERNATIVE_FONT 109 | FONT_OBJS = $(addsuffix .o,ALTERNATIVE_FONT) 110 | FONT_BIN = $(addsuffix .bin,ALTERNATIVE_FONT) 111 | FONT_OLDNAME = $(addsuffix $(addsuffix _bin_start, ALTERNATIVE_FONT), _binary_) 112 | FONT_NEWNAME = altfont 113 | 114 | $(FONT_OBJS): $(FONT_BIN) $(MAKEFILE) $(CONFIG_H) 115 | $(ARMOBJCOPY) -I binary -O elf32-littlearm -B arm $(FONT_BIN) --rename-section .data=.rodata --redefine-sym $(FONT_OLDNAME)=$(FONT_NEWNAME) $(FONT_OBJS) 116 | #endif 117 | 118 | #ifdef ENABLE_MBR 119 | MBR_OBJS = mbr.o 120 | #endif 121 | 122 | #ifdef __aarch64__ 123 | OBJS = boot64.o 124 | #else 125 | OBJS = boot.o 126 | #endif 127 | OBJS += main.o libfs.o $(SERIAL_OBJS) stdio.o stream.o atag.o 128 | OBJS += mbox.o $(FONT_OBJS) $(FB_OBJS) stdlib.o mmio.o heap.o malloc.o 129 | OBJS += printf.o $(SD_OBJS) block.o $(MBR_OBJS) $(FAT_OBJS) vfs.o multiboot.o 130 | OBJS += memchunk.o $(EXT2_OBJS) elf.o timer.o strtol.o strtoll.o $(ASSERT_OBJS) 131 | OBJS += ctype.o $(USB_OBJS) output.o $(RASPBOOTIN_OBJS) $(RAMDISK_OBJS) 132 | OBJS += $(NOFS_OBJS) $(CACHE_OBJS) $(LOGFILE_OBJS) crc32.o rpifdt.o strstr.o 133 | OBJS += config_parse.o 134 | 135 | LIBFS_OBJS = libfs.o $(SD_OBJS) block.o $(MBR_OBJS) $(FAT_OBJS) vfs.o $(EXT2_OBJS) timer.o mmio.o $(RASPBOOTIN_OBJS) $(RAMDISK_OBJS) $(NOFS_OBJS) $(CACHE_OBJS) crc32.o $(ASSERT_OBJS) 136 | 137 | QEMUFW_OBJS = qemufw.o 138 | 139 | export CFLAGS 140 | 141 | .PHONY: clean 142 | .PHONY: qemu 143 | .PHONY: qemu-gdb 144 | .PHONY: dump 145 | .PHONY: $(LIBFTD) 146 | 147 | $(LIBFDT): 148 | cd libdtc && $(MAKE) libfdt/libfdt.a 149 | 150 | dump: $(DISASM_DUMP) 151 | 152 | libfs.a: $(LIBFS_OBJS) 153 | $(ARMAR) rcs $@ $(LIBFS_OBJS) 154 | 155 | qemufw.elf: $(OBJS) qemufw.ld $(LIBFDT) $(QEMUFW_OBJS) 156 | $(ARMCC) -nostdlib $(OBJS) $(QEMUFW_OBJS) -Wl,-T,qemufw.ld -o $@ -Llibdtc/libfdt -lfdt -lgcc 157 | 158 | kernel.elf: $(OBJS) linker.ld $(LIBFDT) 159 | $(ARMCC) -nostdlib $(OBJS) -Wl,-T,linker.ld -o $@ -Llibdtc/libfdt -lfdt -lgcc 160 | 161 | kernel.img: kernel.elf 162 | $(ARMOBJCOPY) kernel.elf -O binary kernel.img 163 | 164 | kernel.img-atag: kernel.img mkknlimg 165 | ./mkknlimg kernel.img kernel.img-atag 166 | 167 | kernel-qemu.elf: $(OBJS) linker-qemu.ld $(LIBFDT) 168 | $(ARMCC) -nostdlib $(OBJS) -Wl,-T,linker-qemu.ld -o $@ -Llibdtc/libfdt -lfdt -lgcc 169 | 170 | kernel-qemu.img: kernel-qemu.elf 171 | $(ARMOBJCOPY) kernel-qemu.elf -O binary kernel-qemu.img 172 | 173 | clean: 174 | $(RM) -f $(OBJS) $(DISASM_DUMP) kernel.elf kernel.img kernel-qemu.img kernel-qemu.elf $(MAKEFILE) kernel.img-preheader kernel.img-atag libfs.a assert.o $(QEMUFW_OBJS) 175 | cd libdtc && $(MAKE) clean 176 | 177 | %.o: %.c $(MAKEFILE) $(CONFIG_H) 178 | $(ARMCC) $(CFLAGS) -include $(CONFIG_H) -c $< -o $@ 179 | 180 | %.o: %.s $(MAKEFILE) $(CONFIG_H) 181 | $(ARMCC) $(ASFLAGS) -include $(CONFIG_H) -c $< -o $@ 182 | 183 | qemu: kernel-qemu.img 184 | if [ -f sd.img ]; then \ 185 | $(QEMU) $(QEMUFLAGS) -drive if=sd,format=raw,file=sd.img; \ 186 | else \ 187 | $(QEMU) $(QEMUFLAGS); \ 188 | fi 189 | 190 | qemu-gdb: kernel-qemu.img 191 | if [ -f sd.img ]; then \ 192 | $(QEMU) $(QEMUFLAGS) -sd sd.img -s -S; \ 193 | else \ 194 | $(QEMU) $(QEMUFLAGS) -s -S; \ 195 | fi 196 | 197 | $(DISASM_DUMP): kernel.elf 198 | $(ARMOBJDUMP) -D kernel.elf > $(DISASM_DUMP) 199 | 200 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | rpi-boot 2 | -------- 3 | 4 | A simple second stage boot loader for the Raspberry Pi to assist in the 5 | development of hobby kernels. 6 | 7 | 8 | Features 9 | -------- 10 | 11 | * Supports booting flat binary files, ELF executables and ELF and a.out 12 | executables with a Multiboot header. Linux kernels are currently not 13 | supported (but support is planned for a future version). 14 | 15 | * Supports FAT(16/32) and ext2 filesystems. 16 | 17 | * Supports loading additional modules when in Multiboot mode. 18 | 19 | * Proviedes functions to the loaded kernel to allow it to easily 20 | access the framebuffer (via a printf() interface) and the filesystem 21 | (via fopen/fread/fclose/opendir/readdir/closedir). 22 | 23 | 24 | Installation 25 | ------------ 26 | 27 | Edit config.h to your needs to enable/disable certain functionality. 28 | 29 | Run make in the source directory and copy the kernel.img file to the SD card 30 | containing your Raspian distribution. You are recommended to backup your 31 | original kernel.img file first. 32 | 33 | 34 | Usage 35 | ----- 36 | 37 | The rpi-boot bootloader will initially search for files called 38 | /boot/rpi_boot.cfg, /boot/rpi-boot.cfg and /boot/grub/grub.cfg (in that order) 39 | on the first partition of the SD card. If one is not found, it searches for 40 | those files on each filesystem known to the system. 41 | 42 | It understands the following commands: 43 | 44 | multiboot [cmdline] 45 | - Load a multiboot compliant kernel 46 | 47 | module [name] 48 | - Load an additional Multiboot module 49 | 50 | kernel 51 | - Load a non-multiboot compliant kernel 52 | 53 | boot 54 | - Boot the kernel 55 | 56 | binary_load_addr
57 | - Set the load address for a flat binary file subsequently loaded by the 58 | 'kernel' command 59 | 60 | entry_addr
61 | - Set the entry point that is jumped to by a subsequent 'boot' command 62 | 63 | console_log [+] [buffer_size] 64 | - Copy the console log to a file. If '+' is specified after the file name 65 | then append to the file instead of overwriting it. If 'buffer_size' 66 | is specified then it is the number of bytes to buffer before writing 67 | to the file. This prevents the log quickly using up all the write 68 | cycles on solid state media, but runs the risk of some messages being 69 | lost on a kernel crash. Call fflush(get_log_file()) from the guest 70 | OS to manually flush the buffer. Support for console_log requires 71 | that ENABLE_CONSOLE_LOGFILE be enabled in config.h 72 | 73 | 74 | System state on kernel start 75 | ---------------------------- 76 | 77 | For Multiboot kernels, the system state is defined in MULTIBOOT-ARM, otherwise: 78 | 79 | r0 will be 0 80 | r1 will be the ARM machine type 81 | r2 will be the address of the ATAGs 82 | 83 | (the above 3 are identical to the ARM Linux boot protocol) 84 | 85 | r3 will be the address of the multiboot_arm_functions structure as defined in 86 | MULTIBOOT-ARM. 87 | 88 | See the test-kernel directory for an example. 89 | 90 | 91 | Caveats 92 | ------- 93 | 94 | rpi-boot occupies the first 1 MiB of memory for itself. If you wish to make 95 | use of the multiboot_arm_functions functions you need to preserve this. If 96 | not you can overwrite it from within your kernel. If you do overwrite it, 97 | you should make sure you have already obtained all the information you need 98 | from the various Multiboot structures (or copied them elsewhere). 99 | 100 | Because of this, rpi-boot will not boot kernels which are linked below 1 MiB. 101 | 102 | 103 | Licence 104 | ------- 105 | 106 | rpi-boot is released under a MIT licence (see main.c for an example). 107 | 108 | mkknlimg is released under the GPL (see LICENCE.GPL) 109 | The rpi device tree dtb files are Copyright Broadcom (see LICENCE.broadcom) 110 | 111 | The contents of the libdtc directory are the Device Tree Compiler. See 112 | libdtc/libfdt/libfdt.h for conditions. 113 | 114 | strstr.c is taken from the musl C library (see LICENCE.musl) 115 | 116 | 117 | -------------------------------------------------------------------------------- /assert.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by github.org/JamesC1 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | /* Use of libgcc unwinder added by John Cronin 17/6/13 */ 23 | 24 | #include "assert.h" 25 | 26 | #ifdef HAVE_UNWIND_H 27 | #include 28 | #endif 29 | 30 | #include 31 | 32 | #ifdef HAVE_UNWIND_H 33 | static _Unwind_Reason_Code unwind_cb(struct _Unwind_Context *ctx, void *trace_argument) 34 | { 35 | int *depth = (int *)trace_argument; 36 | printf("%i:\tFunction: %08x, IP: %08x\n", *depth, _Unwind_GetRegionStart(ctx), 37 | _Unwind_GetIP(ctx)); 38 | (*depth)++; 39 | 40 | return _URC_NO_REASON; 41 | } 42 | 43 | void assertStackDump(void) 44 | { 45 | printf("\nStack dump:\n"); 46 | int depth = 0; 47 | _Unwind_Backtrace(unwind_cb, &depth); 48 | } 49 | #else 50 | void assertStackDump(void) { 51 | uint32_t start = 0x12345678; 52 | int rowcount = 20; 53 | uint32_t *rowpos = &start; 54 | 55 | printf("\nStack dump:\n"); 56 | 57 | while (rowcount--) { 58 | printf("%06x: %08x %08x %08x %08x %08x %08x %08x %08x\n", 59 | rowpos, rowpos[0], rowpos[1], rowpos[2], rowpos[3], 60 | rowpos[4], rowpos[5], rowpos[6], rowpos[7]); 61 | rowpos += 8; 62 | } 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /assert.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by github.org/JamesC1 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef ASSERT_H 23 | #define ASSERT_H 24 | 25 | #include 26 | 27 | void assertStackDump(void); 28 | 29 | #ifdef DEBUG2 30 | #define DEBUG 31 | #endif 32 | 33 | #ifdef DEBUG 34 | #define assert(x) \ 35 | if(!(x)) {printf("ASSERT: failed: '%s'\n", #x); assertStackDump(); abort();} 36 | #else 37 | #define assert(x) (void)(x) 38 | #endif 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /atag.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include "atag.h" 24 | #include "rpifdt.h" 25 | 26 | #define tag_next(t) (struct atag *)((uint32_t *)(t) + (t)->hdr.size) 27 | 28 | extern const char *atag_cmd_line; 29 | extern int conf_source; 30 | extern uintptr_t _atags; 31 | 32 | int check_atags(const void *atags) 33 | { 34 | const struct atag *cur = (const struct atag *)atags; 35 | if(cur->hdr.tag == ATAG_CORE) 36 | return 0; 37 | return -1; 38 | } 39 | 40 | void parse_atags(uintptr_t atags, 41 | void (*mem_cb)(uint32_t addr, uint32_t len)) 42 | { 43 | if(atags == 0) 44 | return; 45 | 46 | struct atag *cur = (struct atag *)atags; 47 | struct atag *prev; 48 | do 49 | { 50 | prev = cur; 51 | 52 | if(cur->hdr.tag == ATAG_MEM) 53 | mem_cb(cur->u.mem.start, cur->u.mem.size); 54 | else if(cur->hdr.tag == ATAG_CMDLINE) 55 | atag_cmd_line = &cur->u.cmdline.cmdline[0]; 56 | 57 | cur = tag_next(cur); 58 | } while(prev->hdr.tag != ATAG_NONE); 59 | } 60 | 61 | void parse_atag_or_dtb(void (*mem_cb)(uint32_t addr, uint32_t len)) 62 | { 63 | switch(conf_source) 64 | { 65 | case 1: 66 | parse_atags(_atags, mem_cb); 67 | break; 68 | case 2: 69 | parse_atags(0, mem_cb); 70 | break; 71 | case 3: 72 | parse_dtb((const void *)_atags, mem_cb); 73 | break; 74 | case 4: 75 | parse_dtb((const void *)0, mem_cb); 76 | break; 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /atag.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef ATAG_H 23 | #define ATAG_H 24 | 25 | #include 26 | 27 | struct atag_header { 28 | uint32_t size; 29 | uint32_t tag; 30 | }; 31 | 32 | #define ATAG_NONE 0 33 | #define ATAG_CORE 0x54410001 34 | #define ATAG_MEM 0x54410002 35 | #define ATAG_VIDEOTEXT 0x54410003 36 | #define ATAG_RAMDISK 0x54410004 37 | #define ATAG_INITRD2 0x54420005 38 | #define ATAG_SERIAL 0x54410006 39 | #define ATAG_REVISION 0x54410007 40 | #define ATAG_VIDEOLFB 0x54410008 41 | #define ATAG_CMDLINE 0x54410009 42 | 43 | struct atag_core { 44 | uint32_t flags; /* bit 0 = read-only */ 45 | uint32_t pagesize; /* systems page size (usually 4k) */ 46 | uint32_t rootdev; /* root device number */ 47 | }; 48 | 49 | struct atag_mem { 50 | uint32_t size; /* size of the area */ 51 | uint32_t start; /* physical start address */ 52 | }; 53 | 54 | struct atag_videotext { 55 | uint8_t x; /* width of display */ 56 | uint8_t y; /* height of display */ 57 | uint16_t video_page; 58 | uint8_t video_mode; 59 | uint8_t video_cols; 60 | uint16_t video_ega_bx; 61 | uint8_t video_lines; 62 | uint8_t video_isvga; 63 | uint16_t video_points; 64 | }; 65 | 66 | struct atag_ramdisk { 67 | uint32_t flags; /* bit 0 = load, bit 1 = prompt */ 68 | uint32_t size; /* decompressed ramdisk size in _kilo_ bytes */ 69 | uint32_t start; /* starting block of floppy-based RAM disk image */ 70 | }; 71 | 72 | struct atag_initrd2 { 73 | uint32_t start; /* physical start address */ 74 | uint32_t size; /* size of compressed ramdisk image in bytes */ 75 | }; 76 | 77 | struct atag_serialnr { 78 | uint32_t low; 79 | uint32_t high; 80 | }; 81 | 82 | struct atag_revision { 83 | uint32_t rev; 84 | }; 85 | 86 | struct atag_videolfb { 87 | uint16_t lfb_width; 88 | uint16_t lfb_height; 89 | uint16_t lfb_depth; 90 | uint16_t lfb_linelength; 91 | uint32_t lfb_base; 92 | uint32_t lfb_size; 93 | uint8_t red_size; 94 | uint8_t red_pos; 95 | uint8_t green_size; 96 | uint8_t green_pos; 97 | uint8_t blue_size; 98 | uint8_t blue_pos; 99 | uint8_t rsvd_size; 100 | uint8_t rsvd_pos; 101 | }; 102 | 103 | struct atag_cmdline { 104 | char cmdline[1]; /* this is the minimum size */ 105 | }; 106 | 107 | struct atag 108 | { 109 | struct atag_header hdr; 110 | union { 111 | struct atag_core core; 112 | struct atag_mem mem; 113 | struct atag_videotext videotext; 114 | struct atag_ramdisk ramdisk; 115 | struct atag_initrd2 initrd2; 116 | struct atag_serialnr serialnr; 117 | struct atag_revision revision; 118 | struct atag_videolfb videolfb; 119 | struct atag_cmdline cmdline; 120 | } u; 121 | }; 122 | 123 | int check_atags(const void *atags); 124 | void parse_atags(uintptr_t atags, void (*mem_cb)(uint32_t addr, uint32_t len)); 125 | 126 | void parse_atag_or_dtb(void (*mem_cb)(uint32_t addr, uint32_t len)); 127 | 128 | #endif 129 | 130 | -------------------------------------------------------------------------------- /bcm2709-rpi-2-b.dtb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jncronin/rpi-boot/5be9dff41fdebd19aea33ff8d8ceac4c929ced50/bcm2709-rpi-2-b.dtb -------------------------------------------------------------------------------- /block.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include "block.h" 25 | 26 | #define MAX_TRIES 1 27 | 28 | size_t block_read(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t starting_block) 29 | { 30 | // Read the required number of blocks to satisfy the request 31 | int buf_offset = 0; 32 | uint32_t block_offset = 0; 33 | 34 | if(!dev->read) 35 | return 0; 36 | 37 | // Perform a multi-block read if the device supports it 38 | if(dev->supports_multiple_block_read && ((buf_size / dev->block_size) > 1)) 39 | { 40 | #ifdef BLOCK_DEBUG 41 | printf("block_read: performing multi block read (%i blocks) from " 42 | "block %i on %s\n", buf_size / dev->block_size, starting_block, 43 | dev->device_name); 44 | #endif 45 | return dev->read(dev, buf, buf_size, starting_block); 46 | } 47 | 48 | do 49 | { 50 | size_t to_read = buf_size; 51 | if(to_read > dev->block_size) 52 | to_read = dev->block_size; 53 | 54 | #ifdef BLOCK_DEBUG 55 | printf("block_read: reading %i bytes from block %i on %s\n", to_read, 56 | starting_block + block_offset, dev->device_name); 57 | #endif 58 | 59 | int tries = 0; 60 | while(1) 61 | { 62 | int ret = dev->read(dev, &buf[buf_offset], to_read, 63 | starting_block + block_offset); 64 | if(ret < 0) 65 | { 66 | tries++; 67 | if(tries >= MAX_TRIES) 68 | return ret; 69 | } 70 | else 71 | break; 72 | } 73 | 74 | buf_offset += (int)to_read; 75 | block_offset++; 76 | 77 | if(buf_size < dev->block_size) 78 | buf_size = 0; 79 | else 80 | buf_size -= dev->block_size; 81 | } while(buf_size > 0); 82 | 83 | return (size_t)buf_offset; 84 | } 85 | 86 | size_t block_write(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t starting_block) 87 | { 88 | // Write the required number of blocks to satisfy the request 89 | int buf_offset = 0; 90 | uint32_t block_offset = 0; 91 | 92 | if(!dev->write) 93 | return 0; 94 | 95 | do 96 | { 97 | size_t to_write = buf_size; 98 | if(to_write > dev->block_size) 99 | to_write = dev->block_size; 100 | 101 | #ifdef BLOCK_DEBUG 102 | printf("block_write: writing %i bytes to block %i on %s\n", to_write, 103 | starting_block + block_offset, dev->device_name); 104 | #endif 105 | 106 | int tries = 0; 107 | while(1) 108 | { 109 | int ret = dev->write(dev, &buf[buf_offset], to_write, 110 | starting_block + block_offset); 111 | if(ret < 0) 112 | { 113 | tries++; 114 | if(tries >= MAX_TRIES) 115 | return ret; 116 | } 117 | else 118 | break; 119 | } 120 | 121 | buf_offset += (int)to_write; 122 | block_offset++; 123 | 124 | if(buf_size < dev->block_size) 125 | buf_size = 0; 126 | else 127 | buf_size -= dev->block_size; 128 | } while(buf_size > 0); 129 | 130 | return (size_t)buf_offset; 131 | } 132 | -------------------------------------------------------------------------------- /block.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef BLOCK_H 23 | #define BLOCK_H 24 | 25 | #include 26 | #include 27 | 28 | struct fs; 29 | 30 | struct block_device { 31 | char *driver_name; 32 | char *device_name; 33 | uint8_t *device_id; 34 | size_t dev_id_len; 35 | 36 | int supports_multiple_block_read; 37 | int supports_multiple_block_write; 38 | 39 | int (*read)(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t block_num); 40 | int (*write)(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t block_num); 41 | size_t block_size; 42 | size_t num_blocks; 43 | 44 | struct fs *fs; 45 | }; 46 | 47 | size_t block_read(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t starting_block); 48 | size_t block_write(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t starting_block); 49 | 50 | #endif 51 | 52 | #include "fs.h" 53 | 54 | -------------------------------------------------------------------------------- /boot.s: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | .section ".text.boot" 23 | 24 | .globl Start 25 | 26 | // The following is designed to ensure a v2 pi is not in hyp mode 27 | // It does nothing on v1 28 | Start: 29 | mrs r3,cpsr // get the current program status register 30 | and r3,#0x1f // and mask out the mode bits 31 | cmp r3,#0x1a // are we in hyp mode? 32 | beq hyp // if we are in hyp mode, go to that section 33 | cpsid iaf,#0x13 // if not switch to svc mode, ensure we have a stack for the kernel; no ints 34 | b cont // and then jump to set up the stack 35 | 36 | // -- from here we are in hyp mode so we need to exception return to the svc mode 37 | hyp: 38 | mrs r3,cpsr // get the cpsr again 39 | and r3,#~0x1f // clear the mode bits 40 | orr r3,#0x013 // set the mode for svc 41 | orr r3,#1<<6|1<<7|1<<8 // disable interrupts as well 42 | msr spsr_cxsf,r3 // and save that in the spsr 43 | 44 | ldr r3,=cont // get the address where we continue 45 | msr elr_hyp,r3 // store that in the elr register 46 | 47 | eret // this is an exception return 48 | 49 | // -- everyone continues from here 50 | cont: 51 | mov sp, #0x8000 52 | 53 | /* Clear out bss */ 54 | ldr r4, =_bss_start 55 | ldr r9, =_bss_end 56 | mov r5, #0 57 | mov r6, #0 58 | mov r7, #0 59 | mov r8, #0 60 | 61 | b .test 62 | 63 | .loop: 64 | /* this does 4x4 = 16 byte stores at once */ 65 | stmia r4!, {r5-r8} /* the '!' increments r4 but only after ('ia') the store */ 66 | .test: 67 | cmp r4, r9 68 | blo .loop 69 | 70 | /* branch and link to kernel_main */ 71 | ldr r3, =kernel_main 72 | blx r3 /* blx may switch to Thumb mode, depending on the target address */ 73 | 74 | halt: 75 | wfe /* equivalent of x86 HLT instruction */ 76 | b halt 77 | 78 | .globl flush_cache 79 | flush_cache: 80 | mov r0, #0 81 | mcr p15, #0, r0, c7, c14, #0 82 | mov pc, lr 83 | 84 | .globl memory_barrier 85 | memory_barrier: 86 | mov r0, #0 87 | mcr p15, #0, r0, c7, c10, #5 88 | mov pc, lr 89 | 90 | .globl read_sctlr 91 | read_sctlr: 92 | mrc p15, #0, r0, c1, c0, #0 93 | mov pc, lr 94 | 95 | .globl quick_memcpy 96 | quick_memcpy: 97 | push {r4-r9} 98 | mov r4, r0 99 | mov r5, r1 100 | 101 | .loopb: 102 | ldmia r5!, {r6-r9} 103 | stmia r4!, {r6-r9} 104 | subs r2, #16 105 | bhi .loopb 106 | 107 | pop {r4-r9} 108 | mov pc, lr 109 | 110 | -------------------------------------------------------------------------------- /boot64.s: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | .section ".text.boot" 23 | 24 | .globl Start 25 | 26 | Start: 27 | adr x20, stack + (1 << 15) 28 | mov sp, x20 29 | 30 | /* Clear out bss */ 31 | ldr x4, =_bss_start 32 | ldr x9, =_bss_end 33 | mov x5, #0 34 | mov x6, #0 35 | 36 | b .test 37 | 38 | .loop: 39 | /* this does 2x8 = 16 byte stores at once */ 40 | stp x5, x6, [x4, #0] 41 | add x4, x4, #16 42 | .test: 43 | cmp x4, x9 44 | blo .loop 45 | 46 | /* branch and link to kernel_main */ 47 | bl kernel_main 48 | 49 | halt: 50 | wfe /* equivalent of x86 HLT instruction */ 51 | b halt 52 | 53 | .globl flush_cache 54 | flush_cache: 55 | mov x0, #0 56 | /* XXX, not used in QEMU */ 57 | ret 58 | 59 | .globl memory_barrier 60 | memory_barrier: 61 | mov x0, #0 62 | dmb sy 63 | ret 64 | 65 | .globl read_sctlr 66 | read_sctlr: 67 | mrs x0, sctlr_el2 68 | ret 69 | 70 | .globl quick_memcpy 71 | quick_memcpy: 72 | mov x10, x0 73 | mov x11, x1 74 | 75 | .loopb: 76 | ldp x12, x13, [x11, #0] 77 | add x11, x11, #16 78 | stp x12, x13, [x10, #0] 79 | add x10, x10, #16 80 | sub x2, x2, #16 81 | cmp x2, #0 82 | bhi .loopb 83 | 84 | ret 85 | 86 | .section ".bss" 87 | .align 4 /* Align on 128bit boundary */ 88 | stack: 89 | .align 15 /* Reserve 32kb of stack */ 90 | 91 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | /* rpi-boot configuration options 2 | * 3 | * Define/undefine any of the following to enable/disable them 4 | * 5 | * Don't use C++ style comments (//) in this file! 6 | */ 7 | 8 | /* Enable a debug build, note that many files require extra defines to enable 9 | full debug output. e.g. to compile with SD debug support build with 10 | CFLAGS=-DEMMC_DEBUG make 11 | 12 | Also affects compiler optimization flags */ 13 | /*#define DEBUG 1*/ 14 | 15 | /* Offset to adjust physical device addresses by when using ATAGS 16 | * (0 for rpi v1, 0x1f000000 for raspi2 without dtb). 17 | * If using DTB these will be ignored - if you still would rather use 18 | * them then using the kernel.img-atag file will force the bootloader 19 | * to use ATAG mode. */ 20 | #define BASE_ADJUST_V1 0 21 | #define BASE_ADJUST_V2 0x1f000000 22 | 23 | /* Enable the framebuffer as an output device */ 24 | #define ENABLE_FRAMEBUFFER 25 | 26 | /* Choose the default font (NB only zero or one font can be selected at a time) */ 27 | #define ENABLE_DEFAULT_FONT 28 | 29 | /* Choose a different font, the following example looks for font0.bin */ 30 | #undef ENABLE_ALTERNATIVE_FONT 31 | 32 | /* Provide the name (example looks for font0.bin) height and width of the alternative font 33 | * See http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads.html#fonts 34 | * for some example fonts 35 | */ 36 | #define ALTERNATIVE_FONT font0 37 | #define ALTERNATIVE_FONT_H 16 38 | #define ALTERNATIVE_FONT_W 8 39 | 40 | /* Define this if the least significant bit of each character is the leftmost one */ 41 | #define ALTERNATIVE_FONT_LSB_LEFT 42 | 43 | /* Enable support for the on-board SD card reader */ 44 | #define ENABLE_SD 45 | 46 | /* Enable support for Master Boot Record parsing (highly recommended if ENABLE_SD is set) */ 47 | #define ENABLE_MBR 48 | 49 | /* Enable support for the FAT filesystem */ 50 | #define ENABLE_FAT 51 | 52 | /* Enable support for the ext2 filesystem */ 53 | #define ENABLE_EXT2 54 | 55 | /* Enable support for the Raspbootin serial protocol */ 56 | #undef ENABLE_RASPBOOTIN 57 | 58 | /* Enable support for the serial port for debugging and Raspbootin (required for ENABLE_RASPBOOTIN) */ 59 | #define ENABLE_SERIAL 60 | 61 | /* Enable experimental USB host support */ 62 | #undef ENABLE_USB 63 | 64 | /* Enable ramdisk support */ 65 | #define ENABLE_RAMDISK 66 | 67 | /* Enable nofs filesystem support */ 68 | #define ENABLE_NOFS 69 | 70 | /* Enable console log file support */ 71 | #define ENABLE_CONSOLE_LOGFILE 72 | 73 | /* Enable block device cache support */ 74 | #define ENABLE_BLOCK_CACHE 75 | 76 | /* Enable write-back cache support (currently not implemented) */ 77 | #undef ENABLE_BLOCK_CACHE_WB 78 | 79 | /* Presence of header file. Modern GCC should have this. */ 80 | #define HAVE_UNWIND_H 81 | 82 | -------------------------------------------------------------------------------- /config_parse.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | // Parses the .cfg file 23 | 24 | #include "config_parse.h" 25 | #include "ctype.h" 26 | #include "stdio.h" 27 | #include "stdlib.h" 28 | #include "string.h" 29 | 30 | static char *read_line(char **buf) 31 | { 32 | char *start = *buf; 33 | char *ptr = *buf; 34 | 35 | if(!*start) 36 | return (void*)0; 37 | while((*ptr != 0) && (*ptr != '\n')) 38 | ptr++; 39 | 40 | if(*ptr == 0) 41 | { 42 | // End of the string 43 | *buf = ptr; 44 | return start; 45 | } 46 | else 47 | { 48 | // End of a line - null terminate 49 | *ptr = 0; 50 | ptr++; 51 | *buf = ptr; 52 | return start; 53 | } 54 | } 55 | 56 | /* Remove leading and trailing whitespace and trailing comments from a configuration line */ 57 | static char *strip_comments(char *buf) 58 | { 59 | // Remove leading whitespace 60 | while(isspace(*buf)) 61 | buf++; 62 | 63 | // Remove comments 64 | char *s = buf; 65 | while(*s) 66 | { 67 | if(*s == '#') 68 | *s = '\0'; 69 | else 70 | s++; 71 | } 72 | 73 | // Remove trailing whitespace 74 | s--; 75 | while((s > buf) && isspace(*s)) 76 | { 77 | *s = '\0'; 78 | s--; 79 | } 80 | 81 | return buf; 82 | } 83 | 84 | const char empty_string[] = ""; 85 | 86 | void split_string(char *str, char delim, char **method, char **args) 87 | { 88 | int state = 0; 89 | char *p = str; 90 | 91 | // state = 0 - reading spaces before method 92 | // 1 - reading method 93 | // 2 - reading spaces before argument 94 | 95 | *method = (char*)empty_string; 96 | *args = (char*)empty_string; 97 | 98 | if (!delim) 99 | delim = ' '; 100 | 101 | while(*p) 102 | { 103 | if(*p == delim) 104 | { 105 | if(state == 1) 106 | { 107 | *p = 0; // null terminate method 108 | state = 2; 109 | } 110 | } 111 | else 112 | { 113 | if(state == 0) 114 | { 115 | *method = p; 116 | state = 1; 117 | } 118 | else if(state == 2) 119 | { 120 | *args = p; 121 | return; 122 | } 123 | } 124 | p++; 125 | } 126 | } 127 | 128 | int config_parse(char *buf, char delim, 129 | const struct config_parse_method *methods) 130 | { 131 | char *line; 132 | char *b = buf; 133 | const struct config_parse_method *curmethod; 134 | 135 | while((line = read_line(&b))) 136 | { 137 | line = strip_comments(line); 138 | #ifdef MULTIBOOT_DEBUG 139 | printf("read_line: %s\n", line); 140 | #endif 141 | char *method, *args; 142 | split_string(line, delim, &method, &args); 143 | #ifdef MULTIBOOT_DEBUG 144 | printf("method: %s, args: %s\n", method, args); 145 | #endif 146 | 147 | if(!strcmp(method, empty_string)) 148 | continue; 149 | 150 | // Find and run the method 151 | int found = 0; 152 | char *lwr = strlwr(method); 153 | 154 | for(curmethod = methods; curmethod->name; curmethod++) 155 | { 156 | if(!strcmp(lwr, curmethod->name)) 157 | { 158 | found = 1; 159 | int retno = curmethod->method(args); 160 | if(retno != 0) 161 | { 162 | printf("cfg_parse: %s failed with " 163 | "%i\n", line, 164 | retno); 165 | free(lwr); 166 | return retno; 167 | } 168 | break; 169 | } 170 | } 171 | 172 | free(lwr); 173 | 174 | if(!found) 175 | printf("cfg_parse: unknown method %s\n", method); 176 | } 177 | 178 | return 0; 179 | } 180 | 181 | -------------------------------------------------------------------------------- /config_parse.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | /* Helper to parse .cfg files */ 23 | 24 | struct config_parse_method 25 | { 26 | char *name; 27 | int (*method)(char *args); 28 | char delim; 29 | }; 30 | 31 | extern const char empty_string[]; 32 | 33 | void split_string(char *str, char delim, char **method, char **args); 34 | int config_parse(char *buf, char delim, 35 | const struct config_parse_method *methods); 36 | -------------------------------------------------------------------------------- /console.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "fb.h" 26 | #include "console.h" 27 | #include "util.h" 28 | 29 | #ifdef ENABLE_DEFAULT_FONT 30 | extern uint8_t vgafont8[]; 31 | #define CHAR_W 8 32 | #define CHAR_H 8 33 | #define FONT vgafont8 34 | #endif 35 | 36 | #ifdef ENABLE_ALTERNATIVE_FONT 37 | #ifdef ENABLE_DEFAULT_FONT 38 | #error Cannot enable both the default and alternative fonts 39 | #endif 40 | #define FONT altfont 41 | extern uint8_t FONT[]; 42 | #define CHAR_W ALTERNATIVE_FONT_W 43 | #define CHAR_H ALTERNATIVE_FONT_H 44 | #ifdef ALTERNATIVE_FONT_LSB_LEFT 45 | #define FONT_LSB_LEFT 46 | #endif 47 | #endif 48 | 49 | #ifndef FONT 50 | #error No console font is defined! Please see config.h 51 | #endif 52 | 53 | // Some fonts are encoded that the least significant byte is to the left, others have it to the right 54 | #ifdef FONT_LSB_LEFT 55 | #define BIT_SHIFT (s_bit_no) 56 | #else 57 | #define BIT_SHIFT (7 - s_bit_no) 58 | #endif 59 | 60 | #define DEF_FORE 0xffffffff 61 | #define DEF_BACK 0x00000000 62 | 63 | static int cur_x = 0; 64 | static int cur_y = 0; 65 | 66 | static uint32_t cur_fore = DEF_FORE; 67 | static uint32_t cur_back = DEF_BACK; 68 | 69 | void clear() 70 | { 71 | int height = fb_get_height(); 72 | int pitch = fb_get_pitch(); 73 | int line_byte_width = fb_get_width() * (fb_get_bpp() >> 3); 74 | uint8_t *fb = (uint8_t *)fb_get_framebuffer(); 75 | 76 | for(int line = 0; line < height; line++) 77 | memset(&fb[line * pitch], 0, line_byte_width); 78 | 79 | cur_x = 0; 80 | cur_y = 0; 81 | } 82 | 83 | #ifdef FONT 84 | void newline() 85 | { 86 | cur_y++; 87 | cur_x = 0; 88 | 89 | // Scroll up if necessary 90 | if(cur_y == fb_get_height() / CHAR_H) 91 | { 92 | uint8_t *fb = (uint8_t *)fb_get_framebuffer(); 93 | int line_byte_width = fb_get_width() * (fb_get_bpp() >> 3); 94 | int pitch = fb_get_pitch(); 95 | int height = fb_get_height(); 96 | 97 | for(int line = 0; line < (height - CHAR_H); line++) 98 | quick_memcpy(&fb[line * pitch], &fb[(line + CHAR_H) * pitch], line_byte_width); 99 | for(int line = height - CHAR_H; line < height; line++) 100 | memset(&fb[line * pitch], 0, line_byte_width); 101 | 102 | cur_y--; 103 | } 104 | } 105 | 106 | int console_putc(int c) 107 | { 108 | int line_w = fb_get_width() / CHAR_W; 109 | 110 | if(c == '\n') 111 | newline(); 112 | else 113 | { 114 | draw_char((char)c, cur_x, cur_y, cur_fore, cur_back); 115 | cur_x++; 116 | if(cur_x == line_w) 117 | newline(); 118 | } 119 | 120 | return c; 121 | } 122 | 123 | void draw_char(char c, int x, int y, uint32_t fore, uint32_t back) 124 | { 125 | volatile uint8_t *fb = (uint8_t *)fb_get_framebuffer(); 126 | int bpp = fb_get_bpp(); 127 | int bytes_per_pixel = bpp >> 3; 128 | 129 | int d_offset = y * CHAR_H * fb_get_pitch() + x * bytes_per_pixel * CHAR_W; 130 | int line_d_offset = d_offset; 131 | int s_offset = (int)c * CHAR_W * CHAR_H; 132 | 133 | for(int c_y = 0; c_y < CHAR_H; c_y++) 134 | { 135 | d_offset = line_d_offset; 136 | 137 | for(int c_x = 0; c_x < CHAR_W; c_x++) 138 | { 139 | int s_byte_no = s_offset / 8; 140 | int s_bit_no = s_offset % 8; 141 | 142 | uint8_t s_byte = FONT[s_byte_no]; 143 | uint32_t colour = back; 144 | if((s_byte >> BIT_SHIFT) & 0x1) 145 | colour = fore; 146 | 147 | for(int i = 0; i < bytes_per_pixel; i++) 148 | { 149 | fb[d_offset + i] = (uint8_t)(colour & 0xff); 150 | colour >>= 8; 151 | } 152 | 153 | d_offset += bytes_per_pixel; 154 | s_offset++; 155 | } 156 | 157 | line_d_offset += fb_get_pitch(); 158 | } 159 | } 160 | #endif 161 | -------------------------------------------------------------------------------- /console.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef CONSOLE_H 23 | #define CONSOLE_H 24 | 25 | void clear(); 26 | void draw_char(char c, int x, int y, uint32_t fore, uint32_t back); 27 | int console_putc(int c); 28 | 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /crc32.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or 3 | * code or tables extracted from it, as desired without restriction. 4 | */ 5 | 6 | /* 7 | * First, the polynomial itself and its table of feedback terms. The 8 | * polynomial is 9 | * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 10 | * 11 | * Note that we take it "backwards" and put the highest-order term in 12 | * the lowest-order bit. The X^32 term is "implied"; the LSB is the 13 | * X^31 term, etc. The X^0 term (usually shown as "+1") results in 14 | * the MSB being 1 15 | * 16 | * Note that the usual hardware shift register implementation, which 17 | * is what we're using (we're merely optimizing it by doing eight-bit 18 | * chunks at a time) shifts bits into the lowest-order term. In our 19 | * implementation, that means shifting towards the right. Why do we 20 | * do it this way? Because the calculated CRC must be transmitted in 21 | * order from highest-order term to lowest-order term. UARTs transmit 22 | * characters in order from LSB to MSB. By storing the CRC this way 23 | * we hand it to the UART in the order low-byte to high-byte; the UART 24 | * sends each low-bit to hight-bit; and the result is transmission bit 25 | * by bit from highest- to lowest-order term without requiring any bit 26 | * shuffling on our part. Reception works similarly 27 | * 28 | * The feedback terms table consists of 256, 32-bit entries. Notes 29 | * 30 | * The table can be generated at runtime if desired; code to do so 31 | * is shown later. It might not be obvious, but the feedback 32 | * terms simply represent the results of eight shift/xor opera 33 | * tions for all combinations of data and CRC register values 34 | * 35 | * The values must be right-shifted by eight bits by the "updcrc 36 | * logic; the shift must be unsigned (bring in zeroes). On some 37 | * hardware you could probably optimize the shift in assembler by 38 | * using byte-swap instructions 39 | * polynomial $edb88320 40 | * 41 | * 42 | * CRC32 code derived from work by Gary S. Brown. 43 | */ 44 | 45 | // Taken from the FreeBSD kernel sources and modified for rpi_boot 46 | #include 47 | #include 48 | 49 | const uint32_t crc32_tab[] = { 50 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 51 | 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 52 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 53 | 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 54 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 55 | 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 56 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 57 | 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 58 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 59 | 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 60 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 61 | 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 62 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 63 | 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 64 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 65 | 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 66 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 67 | 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 68 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 69 | 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 70 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 71 | 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 72 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 73 | 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 74 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 75 | 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 76 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 77 | 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 78 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 79 | 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 80 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 81 | 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 82 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 83 | 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 84 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 85 | 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 86 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 87 | 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 88 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 89 | 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 90 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 91 | 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 92 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 93 | }; 94 | 95 | /* 96 | * A function that calculates the CRC-32 based on the table above is 97 | * given below for documentation purposes. An equivalent implementation 98 | * of this function that's actually used in the kernel can be found 99 | * in sys/libkern.h, where it can be inlined. 100 | */ 101 | uint32_t 102 | crc32(const void *buf, size_t size) 103 | { 104 | const uint8_t *p = buf; 105 | uint32_t crc; 106 | crc = ~0U; 107 | while (size--) 108 | crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 109 | return crc ^ ~0U; 110 | } 111 | 112 | // This is added to support incrementally building the crc from several 113 | // buffers 114 | uint32_t crc32_start() 115 | { 116 | return ~0U; 117 | } 118 | 119 | uint32_t crc32_append(uint32_t crc, const void *buf, size_t size) 120 | { 121 | const uint8_t *p = buf; 122 | while (size--) 123 | crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 124 | return crc; 125 | } 126 | 127 | uint32_t crc32_finish(uint32_t crc) 128 | { 129 | return crc ^ ~0U; 130 | } 131 | 132 | // The rest of this file has been stripped 133 | -------------------------------------------------------------------------------- /crc32.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef CRC32_H 23 | #define CRC32_h 24 | 25 | uint32_t crc32(const void *buf, size_t size); 26 | uint32_t crc32_start(); 27 | uint32_t crc32_append(uint32_t crc, const void *buf, size_t size); 28 | uint32_t crc32_finish(uint32_t crc); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /ctype.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Modified 21 May 2013 for rpi-boot by github.org/JamesC1 3 | */ 4 | 5 | #include "ctype.h" 6 | 7 | int isspace(int c) 8 | /* dervied from rpi-boot strtol.c */ 9 | { 10 | if((c == ' ') || (c == '\f') || (c =='\n') || (c == '\r') || 11 | (c == '\t') || (c == '\v')) 12 | return 1; 13 | else 14 | return 0; 15 | } 16 | 17 | int isdigit(int c) 18 | { 19 | if ((c < '0' || (c > '9'))) 20 | return 0; 21 | else 22 | return 1; 23 | } 24 | 25 | int isalpha(int c) 26 | { 27 | if ((c >= 'a') && (c <= 'z')) 28 | return 1; 29 | else if ((c >= 'A') && (c <= 'Z')) 30 | return 1; 31 | else 32 | return 0; 33 | } 34 | 35 | int isupper(int c) 36 | { 37 | if ((c >= 'A') && (c <= 'Z')) 38 | return 1; 39 | else 40 | return 0; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /ctype.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Modified 21 May 2013 for rpi-boot by github.org/JamesC1 3 | */ 4 | 5 | #ifndef CTYPE_H 6 | #define CTYPE_H 7 | 8 | int isspace(int c); 9 | 10 | int isdigit(int c); 11 | 12 | int isalpha(int c); 13 | 14 | int isupper(int c); 15 | 16 | #endif /* CTYPE_H */ 17 | -------------------------------------------------------------------------------- /dirent.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef DIRENT_H 23 | #define DIRENT_H 24 | 25 | struct dirent; 26 | struct dir_info { 27 | struct dirent *first; 28 | struct dirent *next; 29 | }; 30 | 31 | #ifdef DIR 32 | #undef DIR 33 | #endif 34 | #define DIR struct dir_info 35 | 36 | #include "vfs.h" 37 | #include 38 | #include "multiboot.h" 39 | 40 | 41 | 42 | 43 | #endif 44 | 45 | -------------------------------------------------------------------------------- /dwc_usb.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | /* RPi USB host controller driver 23 | * 24 | * The controller is a Synopsys DWC USB 2 OTG 25 | * 26 | * References: 27 | * Altera cv_54018-1.2, chapter 12, USB 2.0 OTG controller 28 | * Raspberry Pi - USB Controller ver 1.03 by Luke Robertson 29 | * BCM2835 Peripherals Guide 30 | * Chadderz USB driver - https://github.com/Chadderz121/csud 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "mmio.h" 38 | #include "mbox.h" 39 | #include "usb.h" 40 | #include "dwc_usb.h" 41 | #include "timer.h" 42 | 43 | #define SYNOPSYS_ID 0x4f54280a 44 | #define USER_ID 0x2708a000 45 | 46 | #ifdef DEBUG2 47 | #define DWC_USB_DEBUG 48 | #endif 49 | 50 | struct dwc_usb_hcd 51 | { 52 | struct usb_hcd b; 53 | 54 | uint32_t base; 55 | 56 | uint32_t config1; 57 | uint32_t config2; 58 | uint32_t config3; 59 | uint32_t config4; 60 | }; 61 | 62 | static int hcd_id = 0; 63 | static char driver_name[] = "dwc_usb"; 64 | 65 | static int dwc_usb_reset(struct usb_hcd *dev); 66 | static int dwc_usb_send_req(struct usb_hcd *dev, struct usb_request *req); 67 | static int dwc_usb_post_reset_init(struct dwc_usb_hcd *d); 68 | 69 | int dwc_usb_init(struct usb_hcd **dev, uint32_t base) 70 | { 71 | // First check we have a valid controller 72 | uint32_t vendor = mmio_read(base + DWC_USB_SYNOPSYS_ID); 73 | uint32_t userid = mmio_read(base + DWC_USB_USER_ID); 74 | 75 | if(vendor != SYNOPSYS_ID) 76 | { 77 | printf("DWC_USB: invalid vendor id %08x\n", vendor); 78 | return -1; 79 | } 80 | 81 | if(userid != USER_ID) 82 | { 83 | printf("DWC_USB: invalid used id %08x\n", userid); 84 | return -1; 85 | } 86 | 87 | // Build the device structure 88 | int cur_hcd_id = hcd_id++; 89 | 90 | // Limit driver interfaces to 1 currently as we use fixed FIFO addresses 91 | if(cur_hcd_id >= 1) 92 | { 93 | printf("DWC_USB: too many host controllers registered\n"); 94 | return -1; 95 | } 96 | struct dwc_usb_hcd *ret = 97 | (struct dwc_usb_hcd *)malloc(sizeof(struct dwc_usb_hcd)); 98 | ret->b.driver_name = driver_name; 99 | char *device_name = malloc(strlen(driver_name) + 2); 100 | strncpy(device_name, driver_name, strlen(driver_name)); 101 | device_name[strlen(driver_name)] = '0' + cur_hcd_id; 102 | device_name[strlen(driver_name) + 1] = '\0'; 103 | ret->b.device_name = device_name; 104 | ret->base = base; 105 | ret->config1 = mmio_read(base + DWC_USB_CONFIG_1); 106 | ret->config2 = mmio_read(base + DWC_USB_CONFIG_2); 107 | ret->config3 = mmio_read(base + DWC_USB_CONFIG_3); 108 | ret->config4 = mmio_read(base + DWC_USB_CONFIG_4); 109 | 110 | ret->b.reset = dwc_usb_reset; 111 | ret->b.send_req = dwc_usb_send_req; 112 | 113 | // Mask the interrupt line to the ARM 114 | uint32_t ahb_conf = mmio_read(base + DWC_USB_AHB_CONF); 115 | ahb_conf &= ~0x1; 116 | usleep(2000); 117 | mmio_write(base + DWC_USB_AHB_CONF, ahb_conf); 118 | 119 | // Enable all interrupts 120 | usleep(2000); 121 | mmio_write(base + DWC_USB_CORE_IRPT_MASK, 0xffffffff); 122 | 123 | // Power on the USB via the mailbox interface (undocumented - from csud) 124 | mbox_write(0, 0x80); 125 | if(mbox_read(0) != 0x80) 126 | { 127 | printf("DWC_USB: unable to power up USB\n"); 128 | return -1; 129 | } 130 | 131 | // Reset the controller 132 | if(dwc_usb_reset((struct usb_hcd *)ret) != 0) 133 | { 134 | printf("DWC_USB: usb_reset() failed\n"); 135 | return -1; 136 | } 137 | 138 | // Return success 139 | printf("DWC_USB: Initialized host controller %s\n", ret->b.device_name); 140 | *dev = (struct usb_hcd *)ret; 141 | 142 | #ifdef DWC_USB_DEBUG 143 | usleep(2000000); // Pause so we can see the screen 144 | #endif 145 | return 0; 146 | } 147 | 148 | int dwc_usb_post_reset_init(struct dwc_usb_hcd *d) 149 | { 150 | #ifdef DWC_USB_DEBUG 151 | printf("DWC_USB: beginning post reset init\n"); 152 | #endif 153 | 154 | // Clear all interrupts 155 | usleep(2000); 156 | mmio_write(d->base + DWC_USB_CORE_IRPT, 0xffffffff); 157 | 158 | // Clear the power register (write StopPClock - csud does this) 159 | usleep(2000); 160 | mmio_write(d->base + DWC_USB_POWER, 0); 161 | 162 | // Initialize the FIFOs 163 | usleep(2000); 164 | mmio_write(d->base + DWC_USB_RECV_FIFO_SIZE, DWC_USB_FIFO_SIZE << 16); 165 | usleep(2000); 166 | mmio_write(d->base + DWC_USB_NON_PERIODIC_FIFO_SIZE, 167 | (DWC_USB_FIFO_START & 0xffff) | (DWC_USB_FIFO_SIZE << 16)); 168 | usleep(2000); 169 | mmio_write(d->base + DWC_USB_PERIODIC_FIFO_SIZE, 170 | ((DWC_USB_FIFO_START + DWC_USB_FIFO_SIZE) & 0xffff) | 171 | (DWC_USB_FIFO_SIZE << 16)); 172 | 173 | // Power on the host port 174 | usleep(2000); 175 | uint32_t ctrl_status = mmio_read(d->base + DWC_USB_HOST_PORT_CTRL_STATUS); 176 | ctrl_status |= DWC_USB_HPCS_PRTPWR; 177 | mmio_write(d->base + DWC_USB_HOST_PORT_CTRL_STATUS, ctrl_status); 178 | 179 | #ifdef DWC_USB_DEBUG 180 | printf("DWC_USB: completed post reset init\n"); 181 | #endif 182 | 183 | return 0; 184 | } 185 | 186 | int dwc_usb_reset(struct usb_hcd *dev) 187 | { 188 | struct dwc_usb_hcd *d = (struct dwc_usb_hcd *)dev; 189 | 190 | #ifdef DWC_USB_DEBUG 191 | printf("DWC_USB: beginning core reset\n"); 192 | #endif 193 | 194 | // Wait for the AHB IDLE state 195 | TIMEOUT_WAIT(mmio_read(d->base + DWC_USB_CORE_RESET) & (1 << 31), 500000); 196 | if((mmio_read(d->base + DWC_USB_CORE_RESET) & (1 << 31)) == 0) 197 | { 198 | printf("DWC_USB: reset(): timeout waiting for AHB IDLE state\n"); 199 | return -1; 200 | } 201 | 202 | // Raise the core soft reset bit high 203 | uint32_t reset = mmio_read(d->base + DWC_USB_CORE_RESET); 204 | reset |= 0x1; 205 | mmio_write(d->base + DWC_USB_CORE_RESET, reset); 206 | usleep(2000); 207 | 208 | // Wait for core reset to go low and AHB IDLE high 209 | int success = 0; 210 | struct timer_wait *tw = register_timer(500000); 211 | do 212 | { 213 | reset = mmio_read(d->base + DWC_USB_CORE_RESET); 214 | if(((reset & 0x1) == 0) && ((reset & (1 << 31)) != 0)) 215 | { 216 | success = 1; 217 | break; 218 | } 219 | } while(!compare_timer(tw)); 220 | free(tw); 221 | 222 | if(!success) 223 | { 224 | printf("DWC_USB: reset(): timeout waiting for reset (%08x)\n", reset); 225 | return -1; 226 | } 227 | 228 | #ifdef DWC_USB_DEBUG 229 | printf("DWC_USB: core reset complete\n"); 230 | #endif 231 | 232 | dwc_usb_post_reset_init(d); 233 | 234 | return 0; 235 | } 236 | 237 | int dwc_usb_send_req(struct usb_hcd *dev, struct usb_request *req) 238 | { 239 | // TODO 240 | (void)dev; 241 | (void)req; 242 | printf("DWC_USB: usb_send_req(): unimplemented\n"); 243 | while(1); 244 | 245 | return 0; 246 | } 247 | 248 | -------------------------------------------------------------------------------- /dwc_usb.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef DWC_USB_H 23 | #define DWC_USB_H 24 | 25 | // The FIFOs - one page per FIFO 26 | #define DWC_USB_FIFO_SIZE 0x1000 27 | #define DWC_USB_FIFO_LEN (3 * DWC_USB_FIFO_SIZE) 28 | #define DWC_USB_FIFO_START (0x100000 - DWC_USB_FIFO_LEN) 29 | 30 | // Register addresses 31 | #define DWC_USB_BASE 0x20980000 32 | #define DWC_USB_OTG_CTRL 0 33 | #define DWC_USB_OTG_IRPT 4 34 | #define DWC_USB_AHB_CONF 8 35 | #define DWC_USB_CORE_CONF 0xC 36 | #define DWC_USB_CORE_RESET 0x10 37 | #define DWC_USB_CORE_IRPT 0x14 38 | #define DWC_USB_CORE_IRPT_MASK 0x18 39 | #define DWC_USB_RECV_STATUS_DBG 0x1C 40 | #define DWC_USB_STATUS_READ_POP 0x1C 41 | #define DWC_USB_DEVICE_STATUS_READ_POP 0x20 42 | #define DWC_USB_RECV_FIFO_SIZE 0x24 43 | #define DWC_USB_NON_PERIODIC_FIFO_SIZE 0x28 44 | #define DWC_USB_NON_PERIODIC_FIFO 0x2C 45 | #define DWC_USB_I2C_ACCESS 0x30 46 | #define DWC_USB_PHY_VENDOR_CONTROL 0x34 47 | #define DWC_USB_GPIO 0x38 48 | #define DWC_USB_USER_ID 0x3C 49 | #define DWC_USB_SYNOPSYS_ID 0x40 50 | #define DWC_USB_CONFIG_1 0x44 51 | #define DWC_USB_CONFIG_2 0x48 52 | #define DWC_USB_CONFIG_3 0x4C 53 | #define DWC_USB_CONFIG_4 0x50 54 | #define DWC_USB_PERIODIC_FIFO_SIZE 0x100 55 | 56 | #define DWC_USB_HOST_CONF 0x400 57 | #define DWC_USB_HOST_FRAME_INTERVAL 0x404 58 | #define DWC_USB_HOST_FRAME_NUMBER 0x408 59 | #define DWC_USB_HOST_PERIODIC_FIFO 0x410 60 | #define DWC_USB_HOST_ALL_CHAN_IRPT 0x414 61 | #define DWC_USB_HOST_IPRT_MASK 0x418 62 | #define DWC_USB_HOST_FRAME_LIST 0x41C 63 | #define DWC_USB_HOST_PORT_CTRL_STATUS 0x440 64 | 65 | #define DWC_USB_HOST_CHAN_CHAR 0x500 66 | #define DWC_USB_HOST_CHAN_SPLIT_CTRL 0x504 67 | #define DWC_USB_HOST_CHAN_IRPT 0x508 68 | #define DWC_USB_HOST_CHAN_IRPT_MASK 0x50C 69 | #define DWC_USB_HOST_CHAN_TFER_SIZE 0x510 70 | #define DWC_USB_HOST_CHAN_DMA_ADDR 0x514 71 | 72 | #define DWC_USB_POWER 0xE00 73 | 74 | // DWC_USB_HOST_PORT_CTRL_STATUS bits 75 | #define DWC_USB_HPCS_PRTCONNSTS (1 << 0) 76 | #define DWC_USB_HPCS_PRTCONNDET (1 << 1) 77 | #define DWC_USB_HPCS_PRTENA (1 << 2) 78 | #define DWC_USB_HPCS_PRTENCHNG (1 << 3) 79 | #define DWC_USB_HPCS_PRTOVRCURACT (1 << 4) 80 | #define DWC_USB_HPCS_PRTOVRCURCHNG (1 << 5) 81 | #define DWC_USB_HPCS_PRTRES (1 << 6) 82 | #define DWC_USB_HPCS_PRTSUSP (1 << 7) 83 | #define DWC_USB_HPCS_PRTRST (1 << 8) 84 | #define DWC_USB_HPCS_PRTLNSTS (3 << 10) 85 | #define DWC_USB_HPCS_PRTPWR (1 << 12) 86 | #define DWC_USB_HPCS_PRTTSTCTL (15 << 13) 87 | #define DWC_USB_HPCS_PRTSPD (3 << 17) 88 | 89 | #endif 90 | 91 | -------------------------------------------------------------------------------- /elf.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "elf.h" 27 | 28 | int elf32_read_ehdr(FILE *fp, Elf32_Ehdr **ehdr) 29 | { 30 | *ehdr = (Elf32_Ehdr *)malloc(sizeof(Elf32_Ehdr)); 31 | fseek(fp, 0, SEEK_SET); 32 | size_t bytes_to_read = sizeof(Elf32_Ehdr); 33 | size_t bytes_read = fread(*ehdr, 1, sizeof(Elf32_Ehdr), fp); 34 | if(bytes_to_read != bytes_read) 35 | { 36 | free(*ehdr); 37 | return ELF_FILE_LOAD_ERROR; 38 | } 39 | 40 | // Confirm its an ELF file 41 | if(((*ehdr)->e_ident[0] != 0x7f) || ((*ehdr)->e_ident[1] != 'E') || 42 | ((*ehdr)->e_ident[2] != 'L') || 43 | ((*ehdr)->e_ident[3] != 'F')) 44 | { 45 | free(*ehdr); 46 | return ELF_NOT_ELF; 47 | } 48 | 49 | // Confirm its a 32 bit file 50 | if((*ehdr)->e_ident[EI_CLASS] != ELFCLASS32) 51 | { 52 | free(*ehdr); 53 | return ELF_NOT_32_BIT; 54 | } 55 | 56 | // Confirm its a little-endian file 57 | if((*ehdr)->e_ident[EI_DATA] != ELFDATA2LSB) 58 | { 59 | free(*ehdr); 60 | return ELF_NOT_LITTLE_ENDIAN; 61 | } 62 | 63 | // Confirm its an executable file 64 | if((*ehdr)->e_type != ET_EXEC) 65 | { 66 | free(*ehdr); 67 | return ELF_NOT_EXEC; 68 | } 69 | 70 | // Confirm its for the ARM architecture 71 | if((*ehdr)->e_machine != EM_ARM) 72 | { 73 | free(*ehdr); 74 | return ELF_NOT_ARM; 75 | } 76 | return ELF_OK; 77 | } 78 | 79 | int elf32_read_shdrs(FILE *fp, Elf32_Ehdr *ehdr, uint8_t **shdrs) 80 | { 81 | size_t bytes_to_load = (size_t)(ehdr->e_shentsize * ehdr->e_shnum); 82 | fseek(fp, (long)ehdr->e_shoff, SEEK_SET); 83 | *shdrs = (uint8_t *)malloc(bytes_to_load); 84 | size_t bytes_read = fread(*shdrs, 1, bytes_to_load, fp); 85 | if(bytes_read != bytes_to_load) 86 | { 87 | free(*shdrs); 88 | return ELF_FILE_LOAD_ERROR; 89 | } 90 | return ELF_OK; 91 | } 92 | 93 | int elf32_load_section(FILE *fp, Elf32_Shdr *shdr) 94 | { 95 | if(shdr->sh_type == SHT_NOBITS) 96 | memset((void*)(uintptr_t)shdr->sh_addr, 0, shdr->sh_size); 97 | else 98 | { 99 | if(!shdr->sh_offset) 100 | return ELF_NO_OFFSET; 101 | 102 | fseek(fp, (long)shdr->sh_offset, SEEK_SET); 103 | size_t bytes_to_read = (size_t)shdr->sh_size; 104 | size_t bytes_read = fread((void *)(uintptr_t)shdr->sh_addr, 105 | 1, bytes_to_read, fp); 106 | if(bytes_to_read != bytes_read) 107 | return ELF_FILE_LOAD_ERROR; 108 | } 109 | return ELF_OK; 110 | } 111 | 112 | int elf32_read_phdrs(FILE *fp, Elf32_Ehdr *ehdr, uint8_t **phdrs) 113 | { 114 | size_t bytes_to_load = (size_t)(ehdr->e_phentsize * ehdr->e_phnum); 115 | fseek(fp, (long)ehdr->e_phoff, SEEK_SET); 116 | *phdrs = (uint8_t *)malloc(bytes_to_load); 117 | size_t bytes_read = fread(*phdrs, 1, bytes_to_load, fp); 118 | if(bytes_read != bytes_to_load) 119 | { 120 | free(*phdrs); 121 | return ELF_FILE_LOAD_ERROR; 122 | } 123 | return ELF_OK; 124 | } 125 | 126 | int elf32_load_segment(FILE *fp, Elf32_Phdr *phdr) 127 | { 128 | uintptr_t load_address = phdr->p_paddr; 129 | if(phdr->p_filesz) 130 | { 131 | // Load the file image 132 | fseek(fp, (long)phdr->p_offset, SEEK_SET); 133 | size_t bytes_to_load = (size_t)phdr->p_filesz; 134 | size_t bytes_read = fread((void*)load_address, 1, 135 | bytes_to_load, fp); 136 | if(bytes_read != bytes_to_load) 137 | return ELF_FILE_LOAD_ERROR; 138 | load_address += phdr->p_filesz; 139 | } 140 | if(phdr->p_memsz - phdr->p_filesz) 141 | { 142 | // Zero out the rest of the memory image 143 | memset((void*)load_address, 0, phdr->p_memsz - 144 | phdr->p_filesz); 145 | } 146 | return ELF_OK; 147 | } 148 | 149 | -------------------------------------------------------------------------------- /errno.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef ERRNO_H 23 | #define ERRNO_H 24 | 25 | extern int errno; 26 | 27 | #define ENOMEM -1 28 | #define EINVAL -2 29 | #define ENOENT -3 30 | #define ENOTDIR -4 31 | #define EFAULT -5 32 | #define EROFS -6 33 | #define ERANGE -7 34 | #define ENOSPC -8 35 | 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /fb.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "mbox.h" 26 | #include "fb.h" 27 | 28 | #define WIDTH 640 29 | #define HEIGHT 480 30 | #define BYTES_PER_PIXEL 2 31 | #define BPP (BYTES_PER_PIXEL << 3) 32 | #define S_PITCH (WIDTH * BYTES_PER_PIXEL) // The pitch of the backbuffer 33 | 34 | #define TAG_ALLOCATE_BUFFER 0x40001 35 | #define TAG_RELEASE_BUFFER 0x48001 36 | #define TAG_BLANK_SCREEN 0x40002 37 | #define TAG_GET_PHYS_WH 0x40003 38 | #define TAG_TEST_PHYS_WH 0x44003 39 | #define TAG_SET_PHYS_WH 0x48003 40 | #define TAG_GET_VIRT_WH 0x40004 41 | #define TAG_TEST_VIRT_WH 0x44004 42 | #define TAG_SET_VIRT_WH 0x48004 43 | #define TAG_GET_DEPTH 0x40005 44 | #define TAG_TEST_DEPTH 0x44005 45 | #define TAG_SET_DEPTH 0x48005 46 | #define TAG_GET_PIXEL_ORDER 0x40006 47 | #define TAG_TEST_PIXEL_ORDER 0x44006 48 | #define TAG_SET_PIXEL_ORDER 0x48006 49 | #define TAG_GET_ALPHA_MODE 0x40007 50 | #define TAG_TEST_ALPHA_MODE 0x44007 51 | #define TAG_SET_ALPHA_MODE 0x48007 52 | #define TAG_GET_PITCH 0x40008 53 | #define TAG_GET_VIRT_OFFSET 0x40009 54 | #define TAG_TEST_VIRT_OFFSET 0x44009 55 | #define TAG_SET_VIRT_OFFSET 0x48009 56 | #define TAG_GET_OVERSCAN 0x4000a 57 | #define TAG_TEST_OVERSCAN 0x4400a 58 | #define TAG_SET_OVERSCAN 0x4800a 59 | #define TAG_GET_PALETTE 0x4000b 60 | #define TAG_TEST_PALETTE 0x4400b 61 | #define TAG_SET_PALETTE 0x4800b 62 | 63 | static uint32_t phys_w, phys_h, virt_w, virt_h, pitch; 64 | static uintptr_t fb_addr, fb_size; 65 | 66 | int fb_init() 67 | { 68 | // define a mailbox buffer 69 | uintptr_t mb_addr = 0x7000; // 0x7000 in L2 cache coherent mode 70 | volatile uint32_t *mailbuffer = (uint32_t *)mb_addr; 71 | 72 | /* Get the display size */ 73 | // set up the buffer 74 | mailbuffer[0] = 8 * 4; // size of this message 75 | mailbuffer[1] = 0; // this is a request 76 | 77 | // next comes the first tag 78 | mailbuffer[2] = TAG_GET_PHYS_WH; // get physical width/height tag 79 | mailbuffer[3] = 0x8; // value buffer size 80 | mailbuffer[4] = 0; // request/response 81 | mailbuffer[5] = 0; // space to return width 82 | mailbuffer[6] = 0; // space to return height 83 | 84 | // closing tag 85 | mailbuffer[7] = 0; 86 | 87 | // send the message 88 | mbox_write(MBOX_PROP, mb_addr); 89 | 90 | // read the response 91 | mbox_read(MBOX_PROP); 92 | 93 | /* Check for a valid response */ 94 | if(mailbuffer[1] != MBOX_SUCCESS) 95 | return FB_FAIL_GET_RESOLUTION; 96 | phys_w = mailbuffer[5]; 97 | phys_h = mailbuffer[6]; 98 | 99 | /* Request 640x480 if not otherwise specified */ 100 | if((phys_w == 0) && (phys_h == 0)) 101 | { 102 | phys_w = WIDTH; 103 | phys_h = HEIGHT; 104 | } 105 | 106 | if((phys_w == 0) || (phys_h == 0)) 107 | return FB_FAIL_INVALID_RESOLUTION; 108 | 109 | /* For now set the physical and virtual sizes to be the same */ 110 | virt_w = phys_w; 111 | virt_h = phys_h; 112 | 113 | /* Now set the physical and virtual sizes and bit depth and allocate the framebuffer */ 114 | mailbuffer[0] = 22 * 4; // size of buffer 115 | mailbuffer[1] = 0; // request 116 | 117 | mailbuffer[2] = TAG_SET_PHYS_WH; 118 | mailbuffer[3] = 8; 119 | mailbuffer[4] = 8; 120 | mailbuffer[5] = phys_w; 121 | mailbuffer[6] = phys_h; 122 | 123 | mailbuffer[7] = TAG_SET_VIRT_WH; 124 | mailbuffer[8] = 8; 125 | mailbuffer[9] = 8; 126 | mailbuffer[10] = virt_w; 127 | mailbuffer[11] = virt_h; 128 | 129 | mailbuffer[12] = TAG_SET_DEPTH; 130 | mailbuffer[13] = 4; 131 | mailbuffer[14] = 4; 132 | mailbuffer[15] = BPP; 133 | 134 | mailbuffer[16] = TAG_ALLOCATE_BUFFER; 135 | mailbuffer[17] = 8; 136 | mailbuffer[18] = 4; // request size = 4, response size = 8 137 | mailbuffer[19] = 16; // requested alignment of buffer, space for returned address 138 | mailbuffer[20] = 0; // space for returned size 139 | 140 | mailbuffer[21] = 0; // terminating tag 141 | 142 | mbox_write(MBOX_PROP, mb_addr); 143 | mbox_read(MBOX_PROP); 144 | 145 | /* Validate the response */ 146 | if(mailbuffer[1] != MBOX_SUCCESS) 147 | return FB_FAIL_SETUP_FB; 148 | 149 | /* Check the allocate_buffer response */ 150 | if(mailbuffer[18] != (MBOX_SUCCESS | 8)) 151 | return FB_FAIL_INVALID_TAG_RESPONSE; 152 | 153 | fb_addr = mailbuffer[19]; 154 | fb_size = mailbuffer[20]; 155 | 156 | if((fb_addr == 0) || (fb_size == 0)) 157 | return FB_FAIL_INVALID_TAG_DATA; 158 | 159 | /* Get the pitch of the display */ 160 | mailbuffer[0] = 7 * 4; 161 | mailbuffer[1] = 0; 162 | 163 | mailbuffer[2] = TAG_GET_PITCH; 164 | mailbuffer[3] = 4; 165 | mailbuffer[4] = 0; 166 | mailbuffer[5] = 0; 167 | 168 | mailbuffer[6] = 0; 169 | 170 | mbox_write(MBOX_PROP, mb_addr); 171 | mbox_read(MBOX_PROP); 172 | 173 | /* Validate the response */ 174 | if(mailbuffer[1] != MBOX_SUCCESS) 175 | return FB_FAIL_INVALID_PITCH_RESPONSE; 176 | if(mailbuffer[4] != (MBOX_SUCCESS | 4)) 177 | return FB_FAIL_INVALID_PITCH_RESPONSE; 178 | 179 | pitch = mailbuffer[5]; 180 | if(pitch == 0) 181 | return FB_FAIL_INVALID_PITCH_DATA; 182 | 183 | return 0; 184 | } 185 | 186 | int fb_get_bpp() 187 | { 188 | return BPP; 189 | } 190 | 191 | int fb_get_byte_size() 192 | { 193 | return virt_w * virt_h * BYTES_PER_PIXEL; 194 | } 195 | 196 | int fb_get_width() 197 | { 198 | return virt_w; 199 | } 200 | 201 | int fb_get_height() 202 | { 203 | return virt_h; 204 | } 205 | 206 | int fb_get_pitch() 207 | { 208 | return pitch; 209 | } 210 | 211 | uint8_t *fb_get_framebuffer() 212 | { 213 | return (uint8_t *)fb_addr; 214 | } 215 | 216 | -------------------------------------------------------------------------------- /fb.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef FB_H 23 | #define FB_H 24 | 25 | #define FB_FAIL_GET_RESOLUTION -1 26 | #define FB_FAIL_INVALID_RESOLUTION -2 27 | #define FB_FAIL_SETUP_FB -3 28 | #define FB_FAIL_INVALID_TAGS -4 29 | #define FB_FAIL_INVALID_TAG_RESPONSE -5 30 | #define FB_FAIL_INVALID_TAG_DATA -6 31 | #define FB_FAIL_INVALID_PITCH_RESPONSE -7 32 | #define FB_FAIL_INVALID_PITCH_DATA -8 33 | 34 | uint8_t *fb_get_framebuffer(); 35 | int fb_init(); 36 | int fb_get_bpp(); 37 | int fb_get_byte_size(); 38 | int fb_get_width(); 39 | int fb_get_height(); 40 | int fb_get_pitch(); 41 | 42 | #endif 43 | 44 | -------------------------------------------------------------------------------- /fs.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef FS_H 23 | #define FS_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include "block.h" 29 | 30 | #define FS_FLAG_SUPPORTS_EMPTY_FNAME 1 31 | 32 | struct fs { 33 | struct block_device *parent; 34 | const char *fs_name; 35 | uint32_t flags; 36 | size_t block_size; 37 | 38 | FILE *(*fopen)(struct fs *, struct dirent *, const char *mode); 39 | size_t (*fread)(struct fs *, void *ptr, size_t byte_size, FILE *stream); 40 | size_t (*fwrite)(struct fs *, void *ptr, size_t byte_size, FILE *stream); 41 | int (*fclose)(struct fs *, FILE *fp); 42 | long (*fsize)(FILE *fp); 43 | int (*fseek)(FILE *stream, long offset, int whence); 44 | long (*ftell)(FILE *fp); 45 | int (*fflush)(FILE *fp); 46 | 47 | struct dirent *(*read_directory)(struct fs *, char **name); 48 | }; 49 | 50 | int register_fs(struct block_device *dev, int part_id); 51 | int fs_interpret_mode(const char *mode); 52 | size_t fs_fread(uint32_t (*get_next_bdev_block_num)(uint32_t f_block_idx, FILE *s, void *opaque, int add_blocks), 53 | struct fs *fs, void *ptr, size_t byte_size, 54 | FILE *stream, void *opaque); 55 | size_t fs_fwrite(uint32_t (*get_next_bdev_block_num)(uint32_t f_block_idx, FILE *s, void *opaque, int add_blocks), 56 | struct fs *fs, void *ptr, size_t byte_size, 57 | FILE *stream, void *opaque); 58 | 59 | #endif 60 | 61 | -------------------------------------------------------------------------------- /heap.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #define MAX_BRK (((uintptr_t)&_start - 0x8000) + 0xf0000) 26 | 27 | #ifdef ENABLE_USB 28 | #include "dwc_usb.h" 29 | #define MAX_BUF DWC_USB_FIFO_START 30 | #else 31 | #define MAX_BUF 0x100000 32 | #endif 33 | 34 | extern char _start, _end; 35 | 36 | uintptr_t cur_brk = 0; 37 | uintptr_t cur_buf = MAX_BRK; 38 | 39 | uintptr_t alloc_buf(size_t size) 40 | { 41 | uintptr_t old_buf = cur_buf; 42 | 43 | cur_buf += size; 44 | if(cur_buf > MAX_BUF) 45 | { 46 | cur_buf = old_buf; 47 | return 0; 48 | } 49 | // Align up to a 512 byte value 50 | if(cur_buf & 0x1ff) 51 | { 52 | cur_buf &= ~0x1ff; 53 | cur_buf += 0x200; 54 | } 55 | return old_buf; 56 | } 57 | 58 | void *sbrk(uint32_t increment) 59 | { 60 | // sbrk returns the previous brk value 61 | 62 | // First set up cur_brk if not done already 63 | if(cur_brk == 0) 64 | { 65 | #ifdef DEBUG2 66 | printf("HEAP: initializing at %p\n", &_end); 67 | #endif 68 | 69 | cur_brk = (uintptr_t)&_end; 70 | if(cur_brk & 0xfff) 71 | { 72 | cur_brk &= 0xfffff000; 73 | cur_brk += 0x1000; 74 | } 75 | } 76 | 77 | uintptr_t old_brk = cur_brk; 78 | 79 | cur_brk += increment; 80 | if(cur_brk >= MAX_BRK) 81 | { 82 | cur_brk = old_brk; 83 | return (void*)-1; 84 | } 85 | return (void*)old_brk; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /linker-qemu.ld: -------------------------------------------------------------------------------- 1 | ENTRY (Start) 2 | 3 | SECTIONS 4 | { 5 | . = 0x10000; 6 | _start = .; 7 | _text_start = .; 8 | .text : 9 | { 10 | KEEP(*(.text.boot)) 11 | *(.text) 12 | } 13 | . = ALIGN(4096); 14 | _text_end = .; 15 | 16 | _rodata_start = .; 17 | .rodata : 18 | { 19 | *(.rodata) 20 | } 21 | . = ALIGN(4096); 22 | _rodata_end = .; 23 | 24 | _data_start = .; 25 | .data : 26 | { 27 | *(.data) 28 | } 29 | . = ALIGN(4096); 30 | _data_end = .; 31 | 32 | _bss_start = .; 33 | .bss : 34 | { 35 | bss = .; 36 | *(.bss) 37 | } 38 | . = ALIGN(4096); 39 | _bss_end = .; 40 | 41 | __exidx_start = .; 42 | .ARM.exidx : 43 | { 44 | *(.ARM.exidx*) 45 | } 46 | __exidx_end = .; 47 | 48 | _end = .; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY (Start) 2 | 3 | SECTIONS 4 | { 5 | . = 0x8000; 6 | _start = .; 7 | _text_start = .; 8 | .text : 9 | { 10 | KEEP(*(.text.boot)) 11 | *(.text) 12 | } 13 | . = ALIGN(4096); 14 | _text_end = .; 15 | 16 | _rodata_start = .; 17 | .rodata : 18 | { 19 | *(.rodata) 20 | } 21 | . = ALIGN(4096); 22 | _rodata_end = .; 23 | 24 | _data_start = .; 25 | .data : 26 | { 27 | *(.data) 28 | } 29 | . = ALIGN(4096); 30 | _data_end = .; 31 | 32 | _bss_start = .; 33 | .bss : 34 | { 35 | bss = .; 36 | *(.bss) 37 | } 38 | . = ALIGN(4096); 39 | _bss_end = .; 40 | 41 | __exidx_start = .; 42 | .ARM.exidx : 43 | { 44 | *(.ARM.exidx*) 45 | } 46 | __exidx_end = .; 47 | 48 | _end = .; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /log.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | /* Based on an idea by https://github.com/JamesC1 */ 23 | 24 | /* Support for writing the console log to a file. 25 | * 26 | * The main problem here is that some devices (e.g. SD cards) have limited 27 | * write cycles, so writing every character to them is problematic. Thus, we 28 | * buffer writes to try and do, e.g. one block at a time. The problem here is 29 | * that if the guest OS crashes at some point, the buffer may not be flushed to 30 | * disk. We try and ameliorate this by 1) providing the guest OS with a 31 | * fflush() function to flush at important moments, and 2) automatically 32 | * flushing if log_putc is called and it has been more than a certain time 33 | * since the last flush. 34 | * 35 | * This can still miss certain log outputs, but is probably the best 36 | * compromise. The ideal situation would be to have a background thread 37 | * periodically flushing the buffer to disk, but as we are only a bootloader, 38 | * we cannot hijack the timer interrupt that the guest OS would probably want 39 | * to use itself. 40 | */ 41 | 42 | #include 43 | #include 44 | #include "timer.h" 45 | #include "vfs.h" 46 | #include "output.h" 47 | 48 | FILE *log_fp = NULL; 49 | uint8_t *log_buf = NULL; 50 | size_t buf_size; 51 | size_t buf_ptr; 52 | struct timer_wait last_update; 53 | 54 | // Time between flushes (requires that log_putc is actually called at some point) 55 | #define LOG_TIMEOUT 5000000 56 | 57 | int log_putc(int c) 58 | { 59 | if(last_update.trigger_value == 0) 60 | last_update = register_timer(LOG_TIMEOUT); 61 | 62 | if(log_buf && buf_size) 63 | { 64 | log_buf[buf_ptr++] = c; 65 | if(buf_ptr >= buf_size) 66 | { 67 | if(log_fp && log_fp->fflush_cb) 68 | { 69 | log_fp->fflush_cb(log_fp); 70 | last_update = register_timer(LOG_TIMEOUT); 71 | } 72 | buf_ptr = 0; 73 | } 74 | return 0; 75 | } 76 | else if(log_fp) 77 | { 78 | // Disable output to the log for the write 79 | rpi_boot_output_state state = output_get_state(); 80 | output_disable_log(); 81 | 82 | // Write one character 83 | fwrite(&c, 1, 1, log_fp); 84 | 85 | // Restore saved output state 86 | output_restore_state(state); 87 | return 0; 88 | } 89 | return EOF; 90 | } 91 | 92 | static int log_fflush(FILE *fp) 93 | { 94 | // Flush the buffer 95 | if(fp && log_buf) 96 | { 97 | // Disable output to the log for the write 98 | rpi_boot_output_state state = output_get_state(); 99 | output_disable_log(); 100 | 101 | // Write the buffer 102 | fwrite(log_buf, 1, buf_ptr, fp); 103 | 104 | // Restore the state 105 | output_restore_state(state); 106 | } 107 | return 0; 108 | } 109 | 110 | int register_log_file(FILE *fp, size_t buffer_size) 111 | { 112 | // If we have a current log, flush it 113 | if(log_fp) 114 | { 115 | fflush(log_fp); 116 | 117 | // deregister fflush callback 118 | log_fp->fflush_cb = NULL; 119 | } 120 | 121 | // If passed NULL, then set no log file 122 | if(fp == NULL) 123 | { 124 | if(log_buf) 125 | free(log_buf); 126 | 127 | // We can still use a buffer without a file, for flushing 128 | // later to the file 129 | if(buffer_size) 130 | log_buf = (uint8_t *)malloc(buffer_size); 131 | else 132 | log_buf = NULL; 133 | buf_size = buffer_size; 134 | buf_ptr = 0; 135 | log_fp = NULL; 136 | return 0; 137 | } 138 | 139 | // Store the fflush callback 140 | fp->fflush_cb = log_fflush; 141 | 142 | // If no current log, and there is a buffer, then flush 143 | // what's in it to the new file 144 | if(!log_fp && log_buf) 145 | { 146 | log_fp = fp; 147 | fflush(fp); 148 | } 149 | 150 | // If we have a buffer free it 151 | if((buf_size != buffer_size) && log_buf) 152 | log_buf = (uint8_t *)realloc(log_buf, buffer_size); 153 | else if(log_buf == NULL) 154 | log_buf = (uint8_t *)malloc(buffer_size); 155 | 156 | buf_size = buffer_size; 157 | buf_ptr = 0; 158 | 159 | // Store the log file pointer 160 | log_fp = fp; 161 | 162 | 163 | return 0; 164 | } 165 | 166 | FILE *get_log_file() 167 | { 168 | return log_fp; 169 | } 170 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef LOG_H 23 | #define LOG_H 24 | 25 | #include "vfs.h" 26 | 27 | #define LOG_DEFAULT_BUFFER_SIZE 512 28 | 29 | int log_putc(int c); 30 | int register_log_file(FILE *fp, size_t buffer_size); 31 | FILE *get_log_file(); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013-2016 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "uart.h" 28 | #include "atag.h" 29 | #include "fb.h" 30 | #include "console.h" 31 | #include "block.h" 32 | #include "vfs.h" 33 | #include "memchunk.h" 34 | #include "usb.h" 35 | #include "dwc_usb.h" 36 | #include "output.h" 37 | #include "log.h" 38 | #include "rpifdt.h" 39 | 40 | #define UNUSED(x) (void)(x) 41 | 42 | uintptr_t _atags; 43 | unsigned long _arm_m_type; 44 | #ifdef __aarch64__ 45 | uintptr_t base_adjust = BASE_ADJUST_V2; 46 | #else 47 | uintptr_t base_adjust = 0; 48 | #endif 49 | 50 | char rpi_boot_name[] = "rpi_boot"; 51 | 52 | const char *atag_cmd_line; 53 | 54 | static char *boot_cfg_names[] = 55 | { 56 | "/boot/rpi_boot.cfg", 57 | "/boot/rpi-boot.cfg", 58 | "/boot/grub/grub.cfg", 59 | 0 60 | }; 61 | 62 | static void mem_cb(uint32_t addr, uint32_t len) 63 | { 64 | #ifdef DEBUG 65 | printf("MEMORY: addr: %x, len: %x\n", addr, len); 66 | #endif 67 | 68 | if(addr < 0x100000) 69 | { 70 | addr = 0x100000; 71 | len -= 0x100000; 72 | } 73 | chunk_register_free(addr, len); 74 | } 75 | 76 | void libfs_init(); 77 | 78 | extern int (*stdout_putc)(int); 79 | extern int (*stderr_putc)(int); 80 | extern int (*stream_putc)(int, FILE*); 81 | extern int def_stream_putc(int, FILE*); 82 | 83 | int multiboot_cfg_parse(char *buf); 84 | 85 | int conf_source = 0; 86 | 87 | __attribute__((__weak__)) void find_and_run_config(void) 88 | { 89 | // Look for a boot configuration file, starting with the default device, 90 | // then iterating through all devices 91 | 92 | FILE *f = (void*)0; 93 | 94 | // Default device 95 | char **fname = boot_cfg_names; 96 | char *found_cfg; 97 | while(*fname) 98 | { 99 | f = fopen(*fname, "r"); 100 | if(f) 101 | { 102 | found_cfg = *fname; 103 | break; 104 | } 105 | 106 | fname++; 107 | } 108 | 109 | if(!f) 110 | { 111 | // Try other devices 112 | char **dev = vfs_get_device_list(); 113 | while(*dev) 114 | { 115 | int dev_len = strlen(*dev); 116 | 117 | fname = boot_cfg_names; 118 | while(*fname) 119 | { 120 | int fname_len = strlen(*fname); 121 | char *new_str = (char *)malloc(dev_len + fname_len + 3); 122 | new_str[0] = 0; 123 | strcat(new_str, "("); 124 | strcat(new_str, *dev); 125 | strcat(new_str, ")"); 126 | strcat(new_str, *fname); 127 | 128 | f = fopen(new_str, "r"); 129 | 130 | if(f) 131 | { 132 | found_cfg = new_str; 133 | break; 134 | } 135 | 136 | free(new_str); 137 | fname++; 138 | } 139 | 140 | if(f) 141 | break; 142 | 143 | dev++; 144 | } 145 | } 146 | 147 | if(!f) 148 | { 149 | printf("MAIN: No bootloader configuration file found\n"); 150 | } 151 | else 152 | { 153 | long flen = fsize(f); 154 | printf("MAIN: Found bootloader configuration: %s\n", found_cfg); 155 | char *buf = (char *)malloc(flen+1); 156 | buf[flen] = 0; // null terminate 157 | fread(buf, 1, flen, f); 158 | fclose(f); 159 | multiboot_cfg_parse(buf); 160 | } 161 | } 162 | 163 | void kernel_main(unsigned long boot_dev, unsigned long arm_m_type, 164 | unsigned long atags) 165 | { 166 | // Hack for newer firmware - assume if atags not specified then they are at 0x100 167 | // We also check the zero address in case this is true - see later 168 | if(atags == 0x0) 169 | atags = 0x100; 170 | 171 | atag_cmd_line = (void *)0; 172 | _atags = atags; 173 | _arm_m_type = arm_m_type; 174 | UNUSED(boot_dev); 175 | 176 | // First use the serial console 177 | stdout_putc = split_putc; 178 | stderr_putc = split_putc; 179 | stream_putc = def_stream_putc; 180 | 181 | output_init(); 182 | output_enable_uart(); 183 | 184 | // try and interpret device tree/atags 185 | if(fdt_check_header((const void *)atags) == 0) 186 | conf_source = 3; 187 | else if(fdt_check_header((const void *)0) == 0) 188 | conf_source = 4; 189 | else if(check_atags((const void *)atags) == 0) 190 | conf_source = 1; 191 | else if(check_atags((const void *)0) == 0) 192 | conf_source = 2; 193 | 194 | switch(conf_source) 195 | { 196 | case 1: 197 | case 2: 198 | // If using ATAGs, need to set up base adjust 199 | // manually 200 | if(arm_m_type == 0xc42) 201 | base_adjust = BASE_ADJUST_V1; 202 | else if(arm_m_type == 0xc43) 203 | base_adjust = BASE_ADJUST_V2; 204 | uart_init(); 205 | #ifdef DEBUG 206 | printf("ATAGS: detected\n"); 207 | #endif 208 | 209 | // Fall through 210 | case 3: 211 | case 4: 212 | parse_atag_or_dtb(mem_cb); 213 | break; 214 | default: 215 | /* Assume we are at least on RPi2 */ 216 | base_adjust = BASE_ADJUST_V2; 217 | mem_cb(0, 512 * 1024 * 1024); 218 | uart_init(); 219 | break; 220 | } 221 | 222 | // dump arguments to main 223 | #ifdef DEBUG 224 | printf("MAIN: boot_dev: %x, arm_m_type: %i, atags: %x\n", boot_dev, 225 | arm_m_type, atags); 226 | #endif 227 | 228 | #ifdef ENABLE_FRAMEBUFFER 229 | int result = fb_init(); 230 | if(result == 0) 231 | { 232 | puts("Successfully set up frame buffer"); 233 | #ifdef DEBUG2 234 | printf("FB: width: %i, height: %i, bpp: %i\n", 235 | fb_get_width(), fb_get_height(), 236 | fb_get_bpp()); 237 | #endif 238 | } 239 | else 240 | { 241 | puts("Error setting up framebuffer:"); 242 | puthex(result); 243 | } 244 | #endif 245 | 246 | // Switch to the framebuffer for output 247 | output_enable_fb(); 248 | 249 | // Allocate a log in memory 250 | #ifdef ENABLE_CONSOLE_LOGFILE 251 | register_log_file(NULL, 0x1000); 252 | output_enable_log(); 253 | #endif 254 | 255 | printf("Welcome to Rpi bootloader\n"); 256 | printf("Compiled on %s at %s\n", __DATE__, __TIME__); 257 | printf("ARM system type is %x\n", arm_m_type); 258 | if(atag_cmd_line != (void *)0) 259 | printf("Command line: %s\n", atag_cmd_line); 260 | 261 | // Register the various file systems 262 | libfs_init(); 263 | 264 | // List devices 265 | printf("MAIN: device list: "); 266 | vfs_list_devices(); 267 | printf("\n"); 268 | 269 | find_and_run_config(); 270 | } 271 | 272 | -------------------------------------------------------------------------------- /mbox.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include "mbox.h" 24 | #include "mmio.h" 25 | 26 | #define MBOX_FULL 0x80000000 27 | #define MBOX_EMPTY 0x40000000 28 | 29 | static uint32_t mbox_base = MBOX_BASE; 30 | 31 | void mbox_set_base(uint32_t base) 32 | { 33 | mbox_base = base; 34 | } 35 | 36 | uint32_t mbox_read(uint8_t channel) 37 | { 38 | while(1) 39 | { 40 | while(mmio_read(mbox_base + MBOX_STATUS) & MBOX_EMPTY); 41 | 42 | uint32_t data = mmio_read(mbox_base + MBOX_READ); 43 | uint8_t read_channel = (uint8_t)(data & 0xf); 44 | if(read_channel == channel) 45 | return (data & 0xfffffff0); 46 | } 47 | } 48 | 49 | void mbox_write(uint8_t channel, uint32_t data) 50 | { 51 | while(mmio_read(mbox_base + MBOX_STATUS) & MBOX_FULL); 52 | mmio_write(mbox_base + MBOX_WRITE, (data & 0xfffffff0) | (uint32_t)(channel & 0xf)); 53 | } 54 | 55 | -------------------------------------------------------------------------------- /mbox.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef MBOX_H 23 | #define MBOX_H 24 | 25 | #include 26 | 27 | #define MBOX_BASE 0x2000b880 28 | 29 | #define MBOX_PEEK 0x10 30 | #define MBOX_READ 0x00 31 | #define MBOX_WRITE 0x20 32 | #define MBOX_STATUS 0x18 33 | #define MBOX_SENDER 0x14 34 | #define MBOX_CONFIG 0x1c 35 | 36 | #define MBOX_FB 1 37 | #define MBOX_PROP 8 38 | 39 | #define MBOX_SUCCESS 0x80000000 40 | 41 | uint32_t mbox_read(uint8_t channel); 42 | void mbox_write(uint8_t channel, uint32_t data); 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /memchunk.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include "memchunk.h" 23 | #include 24 | 25 | struct chunk 26 | { 27 | uint32_t start; 28 | uint32_t length; 29 | struct chunk *next; 30 | }; 31 | 32 | struct chunk *free_list = (void *)0; 33 | struct chunk *used = (void *)0; 34 | 35 | uint32_t max_free = 0; 36 | 37 | // Add a chunk to a list 38 | static void chunk_add(uint32_t start, uint32_t length, struct chunk **list) 39 | { 40 | struct chunk *c = (struct chunk *)malloc(sizeof(struct chunk)); 41 | c->start = start; 42 | c->length = length; 43 | c->next = *list; 44 | *list = c; 45 | } 46 | 47 | // Return 1 if the chunk overlaps an entry in a list, otherwise 0 48 | static int chunk_overlaps(uint32_t start, uint32_t length, struct chunk *list) 49 | { 50 | while(list) 51 | { 52 | uint32_t l_start = list->start; 53 | uint32_t l_end = l_start + list->length; 54 | uint32_t end = start + length; 55 | 56 | if((start < l_end) && (end > l_start)) 57 | return 1; 58 | 59 | list = list->next; 60 | } 61 | 62 | return 0; 63 | } 64 | 65 | // Return 1 if the chunk is wholly contained within an entry in the list, otherwise 0 66 | static int chunk_contains(uint32_t start, uint32_t length, struct chunk *list) 67 | { 68 | while(list) 69 | { 70 | uint32_t l_start = list->start; 71 | uint32_t l_end = l_start + list->length; 72 | uint32_t end = start + length; 73 | 74 | if((start >= l_start) && (end <= l_end)) 75 | return 1; 76 | 77 | list = list->next; 78 | } 79 | 80 | return 0; 81 | } 82 | 83 | // Return 1 if can allocate, otherwise 0 84 | static int chunk_can_allocate(uint32_t start, uint32_t length) 85 | { 86 | if(!chunk_contains(start, length, free_list)) 87 | return 0; 88 | if(chunk_overlaps(start, length, used)) 89 | return 0; 90 | return 1; 91 | } 92 | 93 | void chunk_register_free(uint32_t start, uint32_t length) 94 | { 95 | chunk_add(start, length, &free_list); 96 | 97 | if((start + length) > max_free) 98 | max_free = start + length; 99 | } 100 | 101 | uint32_t chunk_get_any_chunk(uint32_t length) 102 | { 103 | uint32_t test_address = 0; 104 | while(test_address < max_free) 105 | { 106 | if(chunk_can_allocate(test_address, length)) 107 | { 108 | chunk_add(test_address, length, &used); 109 | return test_address; 110 | } 111 | test_address += 0x1000; // Returned page aligned chunks 112 | } 113 | 114 | return 0; 115 | } 116 | 117 | uint32_t chunk_get_chunk(uint32_t start, uint32_t length) 118 | { 119 | if(chunk_can_allocate(start, length)) 120 | { 121 | chunk_add(start, length, &used); 122 | return start; 123 | } 124 | return 0; 125 | } 126 | 127 | 128 | -------------------------------------------------------------------------------- /memchunk.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | // Functions for allocating chunks of large memory 23 | 24 | #ifndef MEMCHUNK_H 25 | #define MEMCHUNK_H 26 | 27 | #include 28 | 29 | void chunk_register_free(uint32_t start, uint32_t length); 30 | uint32_t chunk_get_any_chunk(uint32_t length); 31 | uint32_t chunk_get_chunk(uint32_t start, uint32_t length); 32 | 33 | #endif 34 | 35 | -------------------------------------------------------------------------------- /mkknlimg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # ---------------------------------------------------------------------- 3 | # mkknlimg by Phil Elwell for Raspberry Pi 4 | # based on extract-ikconfig by Dick Streefland 5 | # 6 | # (c) 2009,2010 Dick Streefland 7 | # (c) 2014,2015 Raspberry Pi (Trading) Limited 8 | # 9 | # Licensed under the terms of the GNU General Public License. 10 | # ---------------------------------------------------------------------- 11 | 12 | use strict; 13 | use warnings; 14 | use integer; 15 | 16 | use constant FLAG_PI => 0x01; 17 | use constant FLAG_DTOK => 0x02; 18 | use constant FLAG_DDTK => 0x04; 19 | use constant FLAG_270X => 0x08; 20 | use constant FLAG_283X => 0x10; 21 | 22 | my $trailer_magic = 'RPTL'; 23 | 24 | my $tmpfile1 = "/tmp/mkknlimg_$$.1"; 25 | my $tmpfile2 = "/tmp/mkknlimg_$$.2"; 26 | 27 | my $dtok = 0; 28 | my $ddtk = 0; 29 | my $is_270x = 0; 30 | my $is_283x = 0; 31 | 32 | while (@ARGV && ($ARGV[0] =~ /^-/)) 33 | { 34 | my $arg = shift(@ARGV); 35 | if ($arg eq '--dtok') 36 | { 37 | $dtok = 1; 38 | } 39 | elsif ($arg eq '--ddtk') 40 | { 41 | $ddtk = 1; 42 | } 43 | elsif ($arg eq '--270x') 44 | { 45 | $is_270x = 1; 46 | } 47 | elsif ($arg eq '--283x') 48 | { 49 | $is_283x = 1; 50 | } 51 | else 52 | { 53 | print ("* Unknown option '$arg'\n"); 54 | usage(); 55 | } 56 | } 57 | 58 | usage() if (@ARGV != 2); 59 | 60 | my $kernel_file = $ARGV[0]; 61 | my $out_file = $ARGV[1]; 62 | 63 | if (! -r $kernel_file) 64 | { 65 | print ("* File '$kernel_file' not found\n"); 66 | usage(); 67 | } 68 | 69 | my $wanted_strings = 70 | { 71 | 'bcm2708_fb' => FLAG_PI, 72 | 'brcm,bcm2835-mmc' => FLAG_PI, 73 | 'brcm,bcm2835-sdhost' => FLAG_PI, 74 | 'brcm,bcm2708-pinctrl' => FLAG_PI | FLAG_DTOK, 75 | 'brcm,bcm2835-gpio' => FLAG_PI | FLAG_DTOK, 76 | 'brcm,bcm2708' => FLAG_PI | FLAG_DTOK | FLAG_270X, 77 | 'brcm,bcm2709' => FLAG_PI | FLAG_DTOK | FLAG_270X, 78 | 'brcm,bcm2835' => FLAG_PI | FLAG_DTOK | FLAG_283X, 79 | 'brcm,bcm2836' => FLAG_PI | FLAG_DTOK | FLAG_283X, 80 | 'of_overlay_apply' => FLAG_DTOK | FLAG_DDTK, 81 | }; 82 | 83 | my $res = try_extract($kernel_file, $tmpfile1); 84 | $res ||= try_decompress('\037\213\010', 'xy', 'gunzip', 0, 85 | $kernel_file, $tmpfile1, $tmpfile2); 86 | $res ||= try_decompress('\3757zXZ\000', 'abcde', 'unxz --single-stream', -1, 87 | $kernel_file, $tmpfile1, $tmpfile2); 88 | $res ||= try_decompress('BZh', 'xy', 'bunzip2', 0, 89 | $kernel_file, $tmpfile1, $tmpfile2); 90 | $res ||= try_decompress('\135\0\0\0', 'xxx', 'unlzma', 0, 91 | $kernel_file, $tmpfile1, $tmpfile2); 92 | $res ||= try_decompress('\211\114\132', 'xy', 'lzop -d', 0, 93 | $kernel_file, $tmpfile1, $tmpfile2); 94 | $res ||= try_decompress('\002\041\114\030', 'xy', 'lz4 -d', 1, 95 | $kernel_file, $tmpfile1, $tmpfile2); 96 | 97 | my $append_trailer; 98 | my $trailer; 99 | my $kver = '?'; 100 | 101 | $append_trailer = 1; 102 | 103 | if ($res) 104 | { 105 | $kver = $res->{'kver'} || '?'; 106 | my $flags = $res->{'flags'}; 107 | print("Version: $kver\n"); 108 | 109 | if ($flags & FLAG_PI) 110 | { 111 | $dtok ||= ($flags & FLAG_DTOK) != 0; 112 | $is_270x ||= ($flags & FLAG_270X) != 0; 113 | $is_283x ||= ($flags & FLAG_283X) != 0; 114 | $ddtk ||= ($flags & FLAG_DDTK) != 0; 115 | } 116 | else 117 | { 118 | print ("* This doesn't look like a Raspberry Pi kernel.\n"); 119 | } 120 | } 121 | elsif (!$dtok) 122 | { 123 | print ("* Is this a valid kernel?\n"); 124 | } 125 | 126 | if ($append_trailer) 127 | { 128 | printf("DT: %s\n", $dtok ? "y" : "n"); 129 | printf("DDT: %s\n", $ddtk ? "y" : "n"); 130 | printf("270x: %s\n", $is_270x ? "y" : "n"); 131 | printf("283x: %s\n", $is_283x ? "y" : "n"); 132 | 133 | my @atoms; 134 | 135 | push @atoms, [ $trailer_magic, pack('V', 0) ]; 136 | push @atoms, [ 'KVer', $kver ]; 137 | push @atoms, [ 'DTOK', pack('V', $dtok) ]; 138 | push @atoms, [ 'DDTK', pack('V', $ddtk) ]; 139 | push @atoms, [ '270X', pack('V', $is_270x) ]; 140 | push @atoms, [ '283X', pack('V', $is_283x) ]; 141 | push @atoms, [ '283x', pack('V', $is_283x && !$is_270x) ]; 142 | 143 | $trailer = pack_trailer(\@atoms); 144 | $atoms[0]->[1] = pack('V', length($trailer)); 145 | 146 | $trailer = pack_trailer(\@atoms); 147 | } 148 | 149 | my $ofh; 150 | my $total_len = 0; 151 | 152 | if ($out_file eq $kernel_file) 153 | { 154 | die "* Failed to open '$out_file' for append\n" 155 | if (!open($ofh, '>>', $out_file)); 156 | $total_len = tell($ofh); 157 | } 158 | else 159 | { 160 | die "* Failed to open '$kernel_file'\n" 161 | if (!open(my $ifh, '<', $kernel_file)); 162 | die "* Failed to create '$out_file'\n" 163 | if (!open($ofh, '>', $out_file)); 164 | 165 | my $copybuf; 166 | while (1) 167 | { 168 | my $bytes = sysread($ifh, $copybuf, 64*1024); 169 | last if (!$bytes); 170 | syswrite($ofh, $copybuf, $bytes); 171 | $total_len += $bytes; 172 | } 173 | close($ifh); 174 | } 175 | 176 | if ($trailer) 177 | { 178 | # Pad to word-alignment 179 | syswrite($ofh, "\x000\x000\x000", (-$total_len & 0x3)); 180 | syswrite($ofh, $trailer); 181 | } 182 | 183 | close($ofh); 184 | 185 | exit($trailer ? 0 : 1); 186 | 187 | END { 188 | unlink($tmpfile1) if ($tmpfile1); 189 | unlink($tmpfile2) if ($tmpfile2); 190 | } 191 | 192 | 193 | sub usage 194 | { 195 | print ("Usage: mkknlimg [--dtok] [--270x] [--283x] \n"); 196 | exit(1); 197 | } 198 | 199 | sub try_extract 200 | { 201 | my ($knl, $tmp) = @_; 202 | 203 | my $ver = `strings "$knl" | grep -a -E "^Linux version [1-9]"`; 204 | 205 | return undef if (!$ver); 206 | 207 | chomp($ver); 208 | 209 | my $res = { 'kver'=>$ver }; 210 | $res->{'flags'} = strings_to_flags($knl, $wanted_strings); 211 | 212 | return $res; 213 | } 214 | 215 | 216 | sub try_decompress 217 | { 218 | my ($magic, $subst, $zcat, $idx, $knl, $tmp1, $tmp2) = @_; 219 | 220 | my $pos = `tr "$magic\n$subst" "\n$subst=" < "$knl" | grep -abo "^$subst"`; 221 | if ($pos) 222 | { 223 | chomp($pos); 224 | $pos = (split(/[\r\n]+/, $pos))[$idx]; 225 | return undef if (!defined($pos)); 226 | $pos =~ s/:.*[\r\n]*$//s; 227 | my $cmd = "tail -c+$pos \"$knl\" | $zcat > $tmp2 2> /dev/null"; 228 | my $err = (system($cmd) >> 8); 229 | return undef if (($err != 0) && ($err != 2)); 230 | 231 | return try_extract($tmp2, $tmp1); 232 | } 233 | 234 | return undef; 235 | } 236 | 237 | sub strings_to_flags 238 | { 239 | my ($knl, $strings) = @_; 240 | my $string_pattern = '^('.join('|', keys(%$strings)).')$'; 241 | my $flags = 0; 242 | 243 | my @matches = `strings \"$knl\" | grep -E \"$string_pattern\"`; 244 | foreach my $match (@matches) 245 | { 246 | chomp($match); 247 | $flags |= $strings->{$match}; 248 | } 249 | 250 | return $flags; 251 | } 252 | 253 | sub pack_trailer 254 | { 255 | my ($atoms) = @_; 256 | my $trailer = pack('VV', 0, 0); 257 | for (my $i = $#$atoms; $i>=0; $i--) 258 | { 259 | my $atom = $atoms->[$i]; 260 | $trailer .= pack('a*x!4Va4', $atom->[1], length($atom->[1]), $atom->[0]); 261 | } 262 | return $trailer; 263 | } 264 | -------------------------------------------------------------------------------- /mksdimg.sh: -------------------------------------------------------------------------------- 1 | dd if=/dev/zero bs=1k count=65536 of=sd.img 2 | echo ';;b;;' | sfdisk sd.img 3 | mformat -i sd.img@@1M -t 120 -h 16 -s 63 4 | mcopy -i sd.img@@1M -s test_kernel/* ::/ 5 | 6 | -------------------------------------------------------------------------------- /mmio.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include "mmio.h" 24 | 25 | extern void memory_barrier(); 26 | 27 | extern uintptr_t base_adjust; 28 | 29 | inline void mmio_write(uintptr_t reg, uint32_t data) 30 | { 31 | memory_barrier(); 32 | *(volatile uint32_t *)(reg + base_adjust) = data; 33 | memory_barrier(); 34 | } 35 | 36 | inline uint32_t mmio_read(uintptr_t reg) 37 | { 38 | memory_barrier(); 39 | return *(volatile uint32_t *)(reg + base_adjust); 40 | memory_barrier(); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /mmio.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef MMIO_H 23 | #define MMIO_H 24 | 25 | #include 26 | 27 | void mmio_write(uintptr_t reg, uint32_t data); 28 | uint32_t mmio_read(uintptr_t reg); 29 | 30 | #endif // !MMIO_H 31 | 32 | -------------------------------------------------------------------------------- /multiboot.h: -------------------------------------------------------------------------------- 1 | /* multiboot.h - Multiboot header file. */ 2 | /* Copyright (C) 1999,2003,2007,2008,2009 Free Software Foundation, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY 17 | * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 19 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | // Modified from http://www.gnu.org/software/grub/manual/multiboot/multiboot.html 23 | 24 | #ifndef MULTIBOOT_H 25 | #define MULTIBOOT_H 26 | 27 | #define MULTIBOOT_HEADER_MAGIC 0x1BADB002 28 | #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 29 | 30 | #include 31 | 32 | #if defined(__ARMEL__) || defined(__aarch64__) 33 | #include 34 | #include "timer.h" 35 | #include "output.h" 36 | #ifndef FILE 37 | #ifdef VFS_H 38 | #define FILE struct vfs_file 39 | #else 40 | #define FILE uint32_t * 41 | #endif 42 | #endif 43 | #ifndef DIR 44 | #define DIR uint32_t * 45 | //typedef uint32_t * DIR; 46 | #endif 47 | 48 | #define SEEK_SET 0x1000 49 | #define SEEK_CUR 0x1001 50 | #define SEEK_END 0x1002 51 | #define SEEK_START SEEK_SET 52 | 53 | struct dirent { 54 | struct dirent *next; 55 | char *name; 56 | uint32_t byte_size; 57 | uint8_t is_dir; 58 | void *opaque; 59 | struct fs *fs; 60 | }; 61 | 62 | #define MB_ARM_VERSION 2 63 | 64 | struct multiboot_arm_functions 65 | { 66 | // Console output functions 67 | int (*printf)(const char *format, ...); 68 | void (*clear)(); 69 | 70 | // File/directory read functions 71 | FILE *(*fopen)(const char *path, const char *mode); 72 | size_t (*fread)(void *ptr, size_t size, size_t nmemb, FILE *stream); 73 | int (*fclose)(FILE *fp); 74 | int (*fseek)(FILE *stream, long offset, int whence); 75 | DIR *(*opendir)(const char *name); 76 | struct dirent *(*readdir)(DIR *dirp); 77 | int (*closedir)(DIR *dirp); 78 | 79 | // Timer functions 80 | int (*usleep)(useconds_t usec); 81 | 82 | // Functions for controlling output to framebuffer or serial 83 | rpi_boot_output_state (*output_get_state)(); 84 | void (*output_restore_state)(rpi_boot_output_state state); 85 | void (*output_enable_fb)(); 86 | void (*output_disable_fb)(); 87 | void (*output_enable_uart)(); 88 | void (*output_disable_uart)(); 89 | 90 | // Get the version of the multiboot arm header 91 | int (*mb_arm_version)(); 92 | 93 | // More file functions 94 | int (*feof)(FILE *stream); 95 | int (*ferror)(FILE *stream); 96 | size_t (*fwrite)(void *ptr, size_t size, size_t nmemb, FILE *stream); 97 | long (*fsize)(FILE *stream); 98 | long (*ftell)(FILE *stream); 99 | int (*fflush)(FILE *stream); 100 | 101 | // Ramdisk functions 102 | int (*ramdisk_init)(uintptr_t address, size_t size, int fs_type, char *name); 103 | 104 | // Log functions 105 | int (*register_custom_output_function)(int (*putc_function)(int c)); 106 | void (*output_enable_custom)(); 107 | void (*output_disable_custom)(); 108 | void (*output_enable_log)(); 109 | void (*output_disable_log)(); 110 | int (*register_log_file)(FILE *fp, size_t buffer_size); 111 | FILE *(*get_log_file)(); 112 | }; 113 | 114 | #endif // __ARMEL__ 115 | 116 | typedef struct multiboot_header 117 | { 118 | uint32_t magic; 119 | uint32_t flags; 120 | uint32_t checksum; 121 | uint32_t header_addr; 122 | uint32_t load_addr; 123 | uint32_t load_end_addr; 124 | uint32_t bss_end_addr; 125 | uint32_t entry_addr; 126 | } multiboot_header_t; 127 | 128 | typedef struct aout_symbol_table 129 | { 130 | uint32_t tabsize; 131 | uint32_t strsize; 132 | uint32_t addr; 133 | uint32_t reserved; 134 | } aout_symbol_table_t; 135 | 136 | typedef struct elf_section_header_table 137 | { 138 | uint32_t num; 139 | uint32_t size; 140 | uint32_t addr; 141 | uint32_t shndx; 142 | } elf_section_header_table_t; 143 | 144 | typedef struct multiboot_info 145 | { 146 | uint32_t flags; 147 | uint32_t mem_lower; 148 | uint32_t mem_upper; 149 | #if defined(__ARMEL__) || defined(__aarch64__) 150 | char *boot_device; 151 | char *cmdline; 152 | #else 153 | uint32_t boot_device; 154 | uint32_t cmdline; 155 | #endif 156 | uint32_t mods_count; 157 | uint32_t mods_addr; 158 | union 159 | { 160 | aout_symbol_table_t aout_sym; 161 | elf_section_header_table_t elf_sec; 162 | } u; 163 | uint32_t mmap_length; 164 | uint32_t mmap_addr; 165 | 166 | uint32_t drives_length; 167 | #if defined(__ARMEL__) || defined(__aarch64__) 168 | char **drives_addr; 169 | #else 170 | uint32_t drives_addr; 171 | #endif 172 | 173 | /* ROM configuration table */ 174 | uint32_t config_table; 175 | 176 | /* Boot Loader Name */ 177 | #if defined(__ARMEL__) || defined(__aarch64__) 178 | char *boot_loader_name; 179 | #else 180 | uint32_t boot_loader_name; 181 | #endif 182 | 183 | /* APM table */ 184 | uint32_t apm_table; 185 | 186 | /* Video */ 187 | uint32_t vbe_control_info; 188 | uint32_t vbe_mode_info; 189 | uint16_t vbe_mode; 190 | uint16_t vbe_interface_seg; 191 | uint16_t vbe_interface_off; 192 | uint16_t vbe_interface_len; 193 | 194 | uint64_t framebuffer_addr; 195 | uint32_t framebuffer_pitch; 196 | uint32_t framebuffer_width; 197 | uint32_t framebuffer_height; 198 | uint8_t framebuffer_bpp; 199 | #define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 200 | #define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 201 | #define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 202 | uint8_t framebuffer_type; 203 | union 204 | { 205 | struct 206 | { 207 | uint32_t framebuffer_palette_addr; 208 | uint16_t framebuffer_palette_num_colors; 209 | }; 210 | struct 211 | { 212 | uint8_t framebuffer_red_field_position; 213 | uint8_t framebuffer_red_mask_size; 214 | uint8_t framebuffer_green_field_position; 215 | uint8_t framebuffer_green_mask_size; 216 | uint8_t framebuffer_blue_field_position; 217 | uint8_t framebuffer_blue_mask_size; 218 | }; 219 | }; 220 | } multiboot_info_t; 221 | 222 | typedef struct module 223 | { 224 | uint32_t mod_start; 225 | uint32_t mod_end; 226 | uint32_t string; 227 | uint32_t reserved; 228 | } module_t; 229 | 230 | typedef struct memory_map 231 | { 232 | uint32_t size; 233 | uint32_t base_addr_low; 234 | uint32_t base_addr_high; 235 | uint32_t length_low; 236 | uint32_t length_high; 237 | uint32_t type; 238 | } memory_map_t; 239 | 240 | #endif 241 | 242 | -------------------------------------------------------------------------------- /output.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include "output.h" 23 | #include "uart.h" 24 | #include "console.h" 25 | #include "log.h" 26 | 27 | rpi_boot_output_state ostate; 28 | int (*custom_putc)(int c) = NULL; 29 | 30 | rpi_boot_output_state output_get_state() 31 | { 32 | return ostate; 33 | } 34 | 35 | void output_restore_state(rpi_boot_output_state state) 36 | { 37 | ostate = state; 38 | } 39 | 40 | void output_disable_fb() 41 | { 42 | ostate &= ~RPIBOOT_OUTPUT_FB; 43 | } 44 | 45 | void output_enable_fb() 46 | { 47 | #ifdef ENABLE_FRAMEBUFFER 48 | ostate |= RPIBOOT_OUTPUT_FB; 49 | #endif 50 | } 51 | 52 | void output_disable_uart() 53 | { 54 | ostate &= ~RPIBOOT_OUTPUT_UART; 55 | } 56 | 57 | void output_enable_uart() 58 | { 59 | #ifdef ENABLE_SERIAL 60 | ostate |= RPIBOOT_OUTPUT_UART; 61 | #endif 62 | } 63 | 64 | void output_disable_custom() 65 | { 66 | ostate &= ~RPIBOOT_OUTPUT_CUSTOM; 67 | } 68 | 69 | void output_enable_custom() 70 | { 71 | ostate |= RPIBOOT_OUTPUT_CUSTOM; 72 | } 73 | 74 | void output_disable_log() 75 | { 76 | ostate &= ~RPIBOOT_OUTPUT_LOG; 77 | } 78 | 79 | void output_enable_log() 80 | { 81 | #ifdef ENABLE_CONSOLE_LOGFILE 82 | ostate |= RPIBOOT_OUTPUT_LOG; 83 | #endif 84 | } 85 | 86 | void output_init() 87 | { 88 | ostate = 0; 89 | } 90 | 91 | int split_putc(int c) 92 | { 93 | int ret = 0; 94 | #ifdef ENABLE_SERIAL 95 | if(ostate & RPIBOOT_OUTPUT_UART) 96 | ret = uart_putc(c); 97 | #endif 98 | #ifdef ENABLE_FRAMEBUFFER 99 | if(ostate & RPIBOOT_OUTPUT_FB) 100 | ret = console_putc(c); 101 | #endif 102 | #ifdef ENABLE_CONSOLE_LOGFILE 103 | if(ostate & RPIBOOT_OUTPUT_LOG) 104 | ret = log_putc(c); 105 | #endif 106 | if((ostate & RPIBOOT_OUTPUT_CUSTOM) && custom_putc) 107 | custom_putc(c); 108 | return ret; 109 | } 110 | 111 | int register_custom_output_function(int (*putc_function)(int c)) 112 | { 113 | custom_putc = putc_function; 114 | return 0; 115 | } 116 | -------------------------------------------------------------------------------- /output.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef OUTPUT_H 23 | #define OUTPUT_H 24 | 25 | #include 26 | 27 | typedef uint32_t rpi_boot_output_state; 28 | 29 | #ifdef BUILDING_RPIBOOT 30 | rpi_boot_output_state output_get_state(); 31 | void output_restore_state(rpi_boot_output_state state); 32 | void output_enable_fb(); 33 | void output_disable_fb(); 34 | void output_enable_uart(); 35 | void output_disable_uart(); 36 | void output_enable_log(); 37 | void output_disable_log(); 38 | void output_enable_custom(); 39 | void output_disable_custom(); 40 | void output_init(); 41 | int split_putc(int c); 42 | int register_custom_output_function(int (*putc_function)(int c)); 43 | #endif 44 | 45 | #define RPIBOOT_OUTPUT_FB (1 << 0) 46 | #define RPIBOOT_OUTPUT_UART (1 << 1) 47 | #define RPIBOOT_OUTPUT_LOG (1 << 2) 48 | #define RPIBOOT_OUTPUT_CUSTOM (1 << 3) 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /qemufw.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2017 by Alexander Graf 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "uart.h" 28 | #include "atag.h" 29 | #include "fb.h" 30 | #include "console.h" 31 | #include "block.h" 32 | #include "vfs.h" 33 | #include "memchunk.h" 34 | #include "usb.h" 35 | #include "dwc_usb.h" 36 | #include "output.h" 37 | #include "log.h" 38 | #include "rpifdt.h" 39 | 40 | #include "config_parse.h" 41 | 42 | static int method_kernel(char *args); 43 | static int method_arm_control(char *args); 44 | 45 | #ifdef __aarch64__ 46 | const char *boot_kernel = "kernel8.img"; 47 | #else 48 | const char *boot_kernel = "kernel7.img"; 49 | #endif 50 | uint32_t boot_arm_control; 51 | 52 | static const struct config_parse_method methods[] = 53 | { 54 | { 55 | .name = "kernel", 56 | .method = method_kernel, 57 | }, { 58 | .name = "arm_control", 59 | .method = method_arm_control, 60 | }, { 61 | .name = NULL, 62 | }, 63 | }; 64 | 65 | static int method_kernel(char *args) 66 | { 67 | boot_kernel = args; 68 | 69 | return 0; 70 | } 71 | 72 | static int method_arm_control(char *args) 73 | { 74 | char *endptr; 75 | boot_arm_control = strtol(args, &endptr, 0); 76 | 77 | return 0; 78 | } 79 | 80 | void find_and_run_config(void) 81 | { 82 | char **dev = vfs_get_device_list(); 83 | FILE *f = NULL; 84 | const char *fname = "/config.txt"; 85 | int fname_len = strlen(fname); 86 | const char *found_cfg = NULL; 87 | void (*entry)(long a, long b, long c); 88 | char *kernel_fname; 89 | 90 | /* The default load address for payloads is 0x80000 */ 91 | entry = (void*)0x80000; 92 | 93 | /* Look for config.txt */ 94 | for (dev = vfs_get_device_list(); *dev; dev++) { 95 | int dev_len = strlen(*dev); 96 | char *new_str = (char *)malloc(dev_len + fname_len + 3); 97 | 98 | sprintf(new_str, "(%s)%s", *dev, fname); 99 | f = fopen(new_str, "r"); 100 | 101 | if (f) { 102 | found_cfg = new_str; 103 | break; 104 | } 105 | 106 | free(new_str); 107 | } 108 | 109 | if (f) { 110 | long flen = fsize(f); 111 | char *buf = (char *)malloc(flen+1); 112 | 113 | printf("MAIN: Found bootloader configuration: %s\n", found_cfg); 114 | 115 | /* Read full file */ 116 | buf[flen] = 0; 117 | fread(buf, 1, flen, f); 118 | fclose(f); 119 | 120 | config_parse(buf, '=', methods); 121 | } else { 122 | printf("MAIN: No config.txt file found, using defaults\n"); 123 | } 124 | 125 | if (*dev) { 126 | kernel_fname = malloc(strlen(*dev) + strlen("/") + strlen(boot_kernel) + 1); 127 | sprintf(kernel_fname, "(%s)/%s", *dev, boot_kernel); 128 | } else { 129 | kernel_fname = malloc(strlen("/") + strlen(boot_kernel) + 1); 130 | sprintf(kernel_fname, "/%s", boot_kernel); 131 | } 132 | 133 | f = fopen(kernel_fname, "r"); 134 | if (!f) { 135 | printf("Could not open kernel \"%s\". Aborting\n", boot_kernel); 136 | return; 137 | } 138 | 139 | #ifdef __aarch64__ 140 | if (!(boot_arm_control & 0x200)) { 141 | printf("Sorry, I can not run 32bit kernels. Aborting\n"); 142 | return; 143 | } 144 | #endif 145 | 146 | fread((void*)entry, 1, fsize(f), f); 147 | fclose(f); 148 | 149 | printf("Calling kernel ...\n"); 150 | entry(0, 0, 0); 151 | } 152 | -------------------------------------------------------------------------------- /qemufw.ld: -------------------------------------------------------------------------------- 1 | ENTRY (Start) 2 | 3 | SECTIONS 4 | { 5 | . = 0xb400000; 6 | _start = .; 7 | _text_start = .; 8 | .text : 9 | { 10 | KEEP(*(.text.boot)) 11 | *(.text) 12 | } 13 | . = ALIGN(4096); 14 | _text_end = .; 15 | 16 | _rodata_start = .; 17 | .rodata : 18 | { 19 | *(.rodata) 20 | } 21 | . = ALIGN(4096); 22 | _rodata_end = .; 23 | 24 | _data_start = .; 25 | .data : 26 | { 27 | *(.data) 28 | } 29 | . = ALIGN(4096); 30 | _data_end = .; 31 | 32 | _bss_start = .; 33 | .bss : 34 | { 35 | bss = .; 36 | *(.bss) 37 | } 38 | . = ALIGN(4096); 39 | _bss_end = .; 40 | 41 | __exidx_start = .; 42 | .ARM.exidx : 43 | { 44 | *(.ARM.exidx*) 45 | } 46 | __exidx_end = .; 47 | 48 | _end = .; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /ramdisk.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | /* Support for a ramdisk based in memory */ 23 | 24 | #include 25 | #include 26 | #include "block.h" 27 | #include "vfs.h" 28 | #include "memchunk.h" 29 | #include "string.h" 30 | #include "errno.h" 31 | #include "util.h" 32 | 33 | #define RAMDISK_BLOCK_SIZE 512 34 | static char driver_name[] = "ramdisk"; 35 | 36 | int register_fs(struct block_device *dev, int part_id); 37 | static int ramdisk_write(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t block_no); 38 | static int ramdisk_read(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t block_no); 39 | 40 | struct ramdisk_dev 41 | { 42 | struct block_device bd; 43 | uintptr_t address; 44 | size_t size; 45 | }; 46 | 47 | int ramdisk_init(uintptr_t address, size_t size, int fs_type, char *name) 48 | { 49 | // Allocate memory if requested 50 | if(address == 0) 51 | address = (uintptr_t)chunk_get_any_chunk((uint32_t)size); 52 | if(address == 0) 53 | { 54 | errno = ENOMEM; 55 | return -1; 56 | } 57 | 58 | // First create a ramdisk block device 59 | struct ramdisk_dev *dev = (struct ramdisk_dev *)malloc(sizeof(struct ramdisk_dev)); 60 | if(dev == NULL) 61 | return -1; 62 | 63 | memset(dev, 0, sizeof(struct ramdisk_dev)); 64 | dev->bd.block_size = 512; 65 | dev->bd.device_name = (char *)malloc(strlen(name) + 1); 66 | if(dev->bd.device_name == NULL) 67 | { 68 | free(dev); 69 | return -1; 70 | } 71 | strcpy(dev->bd.device_name, name); 72 | dev->bd.driver_name = driver_name; 73 | dev->bd.supports_multiple_block_read = 1; 74 | dev->bd.supports_multiple_block_write = 1; 75 | dev->bd.read = ramdisk_read; 76 | dev->bd.write = ramdisk_write; 77 | 78 | // Now initialise the filesystem 79 | int ret = register_fs((struct block_device *)dev, fs_type); 80 | if(ret != 0) 81 | free(dev); 82 | return ret; 83 | } 84 | 85 | int ramdisk_write(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t block_no) 86 | { 87 | struct ramdisk_dev *rdev = (struct ramdisk_dev *)dev; 88 | 89 | uintptr_t start_address = rdev->address + (uintptr_t)(rdev->bd.block_size * block_no); 90 | uintptr_t ramdisk_end = rdev->address + rdev->size; 91 | 92 | // Ensure we are not accessing beyond the end of the ramdisk 93 | if(buf_size > (ramdisk_end - start_address)) 94 | buf_size = ramdisk_end - start_address; 95 | 96 | // See if we can do quick copies 97 | if(((start_address & 0xf) == 0) && ((buf_size & 0xf) == 0)) 98 | quick_memcpy((void *)start_address, buf, buf_size); 99 | else 100 | memcpy((void *)start_address, buf, buf_size); 101 | 102 | return buf_size; 103 | } 104 | 105 | int ramdisk_read(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t block_no) 106 | { 107 | struct ramdisk_dev *rdev = (struct ramdisk_dev *)dev; 108 | 109 | uintptr_t start_address = rdev->address + (uintptr_t)(rdev->bd.block_size * block_no); 110 | uintptr_t ramdisk_end = rdev->address + rdev->size; 111 | 112 | // Ensure we are not accessing beyond the end of the ramdisk 113 | if(buf_size > (ramdisk_end - start_address)) 114 | buf_size = ramdisk_end - start_address; 115 | 116 | // See if we can do quick copies 117 | if(((start_address & 0xf) == 0) && ((buf_size & 0xf) == 0)) 118 | quick_memcpy(buf, (void *)start_address, buf_size); 119 | else 120 | memcpy(buf, (void *)start_address, buf_size); 121 | 122 | return buf_size; 123 | } 124 | -------------------------------------------------------------------------------- /raspbootin.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef RASPBOOTIN_H 23 | #define RASPBOOTIN_H 24 | 25 | #define SUCCESS 0 26 | #define PATH_NOT_FOUND -1 27 | #define EOF_ERROR -2 28 | #define CRC_ERROR -3 29 | #define INVALID_CMD -4 30 | #define UNSUPPORTED_CMD -5 31 | #define TIMEOUT -6 32 | #define INVALID_MAGIC -7 33 | #define UNKNOWN_ERROR -8 34 | 35 | #define MAGIC 0x27594131 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /rpi-boot-tools/clipLog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Invoke as ./clipLog.py < input > output 4 | 5 | import sys 6 | 7 | while 1: 8 | b = sys.stdin.read(1) 9 | if b == '\xff': 10 | break 11 | sys.stdout.write(b) 12 | 13 | -------------------------------------------------------------------------------- /rpi-boot-tools/clipLog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # From stdin or a file named on the command-line, read the log until a set of 4 | # ~/s which suggest that we have got to the end of the written portion, 5 | # and store it in the defined directory. 6 | 7 | LOG_STORE=~/buildTrees/PI/logs 8 | 9 | store=$(date "+%Y-%m-%d%_%H:%M:%S.txt"; echo) 10 | # | read store 11 | 12 | echo "Stored at '$store'" 13 | 14 | /usr/bin/sed -ne " 15 | s/~~~~~~~~.*/==END==/ 16 | #t 17 | p 18 | #n 19 | " $* |\ 20 | tee $LOG_STORE/$store 21 | 22 | -------------------------------------------------------------------------------- /rpifdt.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2016 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef RPIFDT_H 23 | #define RPIFDT_H 24 | 25 | #include 26 | 27 | void parse_dtb(const void *dtb, void (*mem_cb)(uint32_t addr, uint32_t length)); 28 | 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /stdio.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "stdio.h" 26 | 27 | const char lowercase[] = "0123456789abcdef"; 28 | const char uppercase[] = "0123456789abcdef"; 29 | 30 | int (*stderr_putc)(int c); 31 | int (*stdout_putc)(int c); 32 | int (*stream_putc)(int c, FILE *stream); 33 | 34 | int fputc(int c, FILE *stream) 35 | { 36 | if(stream == stdout) 37 | return stdout_putc(c); 38 | else if(stream == stderr) 39 | return stderr_putc(c); 40 | else 41 | return stream_putc(c, stream); 42 | } 43 | 44 | int putc(int c, FILE *stream) 45 | { 46 | return fputc(c, stream); 47 | } 48 | 49 | int putchar(int c) 50 | { 51 | return fputc(c, stdout); 52 | } 53 | 54 | int fputs(const char *s, FILE *stream) 55 | { 56 | while(*s) 57 | fputc(*s++, stream); 58 | return 0; 59 | } 60 | 61 | int puts(const char *s) 62 | { 63 | fputs(s, stdout); 64 | fputc('\n', stdout); 65 | return 0; 66 | } 67 | 68 | void puthex(uint32_t val) 69 | { 70 | for(int i = 7; i >= 0; i--) 71 | putchar(lowercase[(val >> (i * 4)) & 0xf]); 72 | } 73 | 74 | void putval(uint32_t val, int base, char *dest, int dest_size, int dest_start, int padding, char *case_str) 75 | { 76 | int i; 77 | 78 | if(padding > (dest_size - dest_start)) 79 | padding = dest_size - dest_start; 80 | 81 | for(i = 0; i < padding; i++) 82 | dest[i + dest_start] = '0'; 83 | 84 | i = 0; 85 | while((val != 0) && (i < (dest_size - dest_start))) 86 | { 87 | uint32_t digit = val % base; 88 | dest[dest_size - i - 1 + dest_start] = case_str[digit]; 89 | i++; 90 | val /= base; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /stdio.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef STDIO_H 23 | #define STDIO_H 24 | 25 | #include 26 | #include 27 | 28 | // Include vfs.h to get the FILE definition 29 | #include "vfs.h" 30 | 31 | #define stdin ((FILE *)0) 32 | #define stdout ((FILE *)1) 33 | #define stderr ((FILE *)2) 34 | 35 | int fputc(int c, FILE *stream); 36 | int fputs(const char *, FILE *stream); 37 | int putc(int c, FILE *stream); 38 | int putchar(int c); 39 | int puts(const char *s); 40 | 41 | int printf(const char *format, ...); 42 | int fprintf(FILE *stream, const char *format, ...); 43 | int sprintf(char *str, const char *format, ...); 44 | int snprintf(char *str, size_t size, const char *format, ...); 45 | 46 | void puthex(uint32_t val); 47 | 48 | #endif 49 | 50 | -------------------------------------------------------------------------------- /stdlib.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | int errno; 28 | 29 | void *memcpy(void *dest, const void *src, size_t n) 30 | { 31 | char *s = (char *)src; 32 | char *d = (char *)dest; 33 | while(n > 0) 34 | { 35 | *d++ = *s++; 36 | n--; 37 | } 38 | return dest; 39 | } 40 | 41 | void *memset(void *s, int c, size_t n) 42 | { 43 | char *dest = (char *)s; 44 | while(n > 0) 45 | { 46 | *dest++ = (char)c; 47 | n--; 48 | } 49 | return s; 50 | } 51 | 52 | void abort(void) 53 | { 54 | fputs("abort() called\n", stdout); 55 | fputs("abort() called\n", stderr); 56 | 57 | while(1); 58 | } 59 | 60 | char *strcpy(char *dest, const char *src) 61 | { 62 | char *d = dest; 63 | while(*src != 0) 64 | *d++ = *src++; 65 | *d = 0; 66 | return dest; 67 | } 68 | 69 | char *strcat(char *dest, const char *src) 70 | { 71 | char *d = dest; 72 | while(*d) d++; 73 | while(*src) *d++ = *src++; 74 | *d = 0; 75 | 76 | return dest; 77 | } 78 | 79 | char *strncpy(char *dest, const char *src, size_t n) 80 | { 81 | char *d = dest; 82 | while((*src != 0) && (n > 0)) 83 | { 84 | *d++ = *src++; 85 | n--; 86 | } 87 | if(n > 0) 88 | *d = 0; 89 | return dest; 90 | } 91 | 92 | size_t strlen(const char *s) 93 | { 94 | size_t ret = 0; 95 | while(*s++ != 0) ret++; 96 | return ret; 97 | } 98 | 99 | int strcmp(const char *s1, const char *s2) 100 | { 101 | while(*s1 || *s2) 102 | { 103 | char s = *s1++ - *s2++; 104 | if(s != 0) 105 | return (int)s; 106 | } 107 | return 0; 108 | } 109 | 110 | int raise(int sig) 111 | { 112 | printf("ERROR: signal %i raised. Halted.\n", sig); 113 | while(1); 114 | return 0; 115 | } 116 | 117 | int tolower(int c) 118 | { 119 | if((c >= 'A') && (c <= 'Z')) 120 | return 'a' + (c - 'A'); 121 | else 122 | return c; 123 | } 124 | 125 | int toupper(int c) 126 | { 127 | if((c >= 'a') && (c <= 'z')) 128 | return 'A' + (c - 'a'); 129 | else 130 | return c; 131 | } 132 | 133 | char *strlwr(char *s) 134 | { 135 | size_t len = strlen(s); 136 | char *ret = (char *)malloc(len + 1); 137 | ret[len] = 0; 138 | 139 | for(size_t i = 0; i < len; i++) 140 | ret[i] = tolower(s[i]); 141 | return ret; 142 | } 143 | 144 | char *strupr(char *s) 145 | { 146 | size_t len = strlen(s); 147 | char *ret = (char *)malloc(len + 1); 148 | ret[len] = 0; 149 | 150 | for(size_t i = 0; i < len; i++) 151 | ret[i] = toupper(s[i]); 152 | return ret; 153 | } 154 | 155 | void *memmove(void *dest, const void *src, size_t n) 156 | { 157 | char *d = (char *)dest; 158 | const char *s = (const char *)src; 159 | 160 | if(d > s) 161 | return memcpy(dest, src, n); 162 | else 163 | { 164 | d += n; 165 | s += n; 166 | 167 | while(n--) 168 | *--d = *--s; 169 | return dest; 170 | } 171 | } 172 | 173 | int memcmp(const void *s1, const void *s2, size_t n) 174 | { 175 | const char *s1c = (const char *)s1; 176 | const char *s2c = (const char *)s2; 177 | 178 | while(n--) 179 | { 180 | int v = *s1c++ - *s2c++; 181 | if(v != 0) 182 | return v; 183 | } 184 | return 0; 185 | } 186 | 187 | size_t strnlen(const char *s, size_t maxlen) 188 | { 189 | size_t cnt = 0; 190 | while(*s++ && maxlen--) 191 | cnt++; 192 | return cnt; 193 | } 194 | 195 | char *strchr(const char *s, int c) 196 | { 197 | const char *sc = (const char *)s; 198 | while(*sc) 199 | { 200 | if(*sc == c) 201 | return (void *)sc; 202 | sc++; 203 | } 204 | return NULL; 205 | } 206 | 207 | void *memchr(const void *s, int c, size_t n) 208 | { 209 | const char *sc = (const char *)s; 210 | while(n--) 211 | { 212 | if(*sc == c) 213 | return (void *)sc; 214 | sc++; 215 | } 216 | return NULL; 217 | } 218 | 219 | -------------------------------------------------------------------------------- /stdlib.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef STDLIB_H 23 | #define STDLIB_H 24 | 25 | #include 26 | #include 27 | 28 | void abort(void); 29 | void *malloc(size_t size); 30 | void *realloc(void *ptr, size_t size); 31 | void free(void *ptr); 32 | long strtol(const char * restrict nptr, char ** restrict endptr, int base); 33 | long long strtoll(const char * restrict nptr, char ** restrict endptr, int base); 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /stream.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | 24 | int def_stream_putc(int c, FILE *stream) 25 | { 26 | (void)(c); (void)(stream); 27 | return 0; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /string.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef STRING_H 23 | #define STRING_H 24 | 25 | #include 26 | 27 | void *memcpy(void *dest, const void *src, size_t n); 28 | void *memset(void *s, int c, size_t n); 29 | int memcmp(const void *s1, const void *s2, size_t n); 30 | void *memmove(void *dest, const void *src, size_t n); 31 | void *memchr(const void *s, int c, size_t n); 32 | size_t strlen(const char *s); 33 | char *strchr(const char *s, int c); 34 | char *strcpy(char *dest, const char *src); 35 | char *strncpy(char *dest, const char *src, size_t n); 36 | int strcmp(const char *s1, const char *s2); 37 | char *strcat(char *dest, const char *src); 38 | int tolower(int c); 39 | int toupper(int c); 40 | char *strlwr(char *s); 41 | char *strupr(char *s); 42 | char *strstr(const char *haystack, const char *needle); 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /strstr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static char *twobyte_strstr(const unsigned char *h, const unsigned char *n) 5 | { 6 | uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1]; 7 | for (h++; *h && hw != nw; hw = hw<<8 | *++h); 8 | return *h ? (char *)h-1 : 0; 9 | } 10 | 11 | static char *threebyte_strstr(const unsigned char *h, const unsigned char *n) 12 | { 13 | uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8; 14 | uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8; 15 | for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8); 16 | return *h ? (char *)h-2 : 0; 17 | } 18 | 19 | static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n) 20 | { 21 | uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3]; 22 | uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3]; 23 | for (h+=3; *h && hw != nw; hw = hw<<8 | *++h); 24 | return *h ? (char *)h-3 : 0; 25 | } 26 | 27 | #define MAX(a,b) ((a)>(b)?(a):(b)) 28 | #define MIN(a,b) ((a)<(b)?(a):(b)) 29 | 30 | #define BITOP(a,b,op) \ 31 | ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) 32 | 33 | static char *twoway_strstr(const unsigned char *h, const unsigned char *n) 34 | { 35 | const unsigned char *z; 36 | size_t l, ip, jp, k, p, ms, p0, mem, mem0; 37 | size_t byteset[32 / sizeof(size_t)] = { 0 }; 38 | size_t shift[256]; 39 | 40 | /* Computing length of needle and fill shift table */ 41 | for (l=0; n[l] && h[l]; l++) 42 | BITOP(byteset, n[l], |=), shift[n[l]] = l+1; 43 | if (n[l]) return 0; /* hit the end of h */ 44 | 45 | /* Compute maximal suffix */ 46 | ip = -1; jp = 0; k = p = 1; 47 | while (jp+k n[jp+k]) { 54 | jp += k; 55 | k = 1; 56 | p = jp - ip; 57 | } else { 58 | ip = jp++; 59 | k = p = 1; 60 | } 61 | } 62 | ms = ip; 63 | p0 = p; 64 | 65 | /* And with the opposite comparison */ 66 | ip = -1; jp = 0; k = p = 1; 67 | while (jp+k ms+1) ms = ip; 83 | else p = p0; 84 | 85 | /* Periodic needle? */ 86 | if (memcmp(n, n+p, ms+1)) { 87 | mem0 = 0; 88 | p = MAX(ms, l-ms-1) + 1; 89 | } else mem0 = l-p; 90 | mem = 0; 91 | 92 | /* Initialize incremental end-of-haystack pointer */ 93 | z = h; 94 | 95 | /* Search loop */ 96 | for (;;) { 97 | /* Update incremental end-of-haystack pointer */ 98 | if (z-h < (ptrdiff_t)l) { 99 | /* Fast estimate for MIN(l,63) */ 100 | size_t grow = l | 63; 101 | const unsigned char *z2 = memchr(z, 0, grow); 102 | if (z2) { 103 | z = z2; 104 | if (z-h < (ptrdiff_t)l) return 0; 105 | } else z += grow; 106 | } 107 | 108 | /* Check last byte first; advance by shift on mismatch */ 109 | if (BITOP(byteset, h[l-1], &)) { 110 | k = l-shift[h[l-1]]; 111 | //printf("adv by %zu (on %c) at [%s] (%zu;l=%zu)\n", k, h[l-1], h, shift[h[l-1]], l); 112 | if (k) { 113 | if (mem0 && mem && k < p) k = l-p; 114 | h += k; 115 | mem = 0; 116 | continue; 117 | } 118 | } else { 119 | h += l; 120 | mem = 0; 121 | continue; 122 | } 123 | 124 | /* Compare right half */ 125 | for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++); 126 | if (n[k]) { 127 | h += k-ms; 128 | mem = 0; 129 | continue; 130 | } 131 | /* Compare left half */ 132 | for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--); 133 | if (k <= mem) return (char *)h; 134 | h += p; 135 | mem = mem0; 136 | } 137 | } 138 | 139 | char *strstr(const char *h, const char *n) 140 | { 141 | /* Return immediately on empty needle */ 142 | if (!n[0]) return (char *)h; 143 | 144 | /* Use faster algorithms for short needles */ 145 | h = strchr(h, *n); 146 | if (!h || !n[1]) return (char *)h; 147 | if (!h[1]) return 0; 148 | if (!n[2]) return twobyte_strstr((void *)h, (void *)n); 149 | if (!h[2]) return 0; 150 | if (!n[3]) return threebyte_strstr((void *)h, (void *)n); 151 | if (!h[3]) return 0; 152 | if (!n[4]) return fourbyte_strstr((void *)h, (void *)n); 153 | 154 | return twoway_strstr((void *)h, (void *)n); 155 | } 156 | -------------------------------------------------------------------------------- /strtol.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1990, 1993 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 4. Neither the name of the University nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | */ 29 | 30 | // Modified for rpi_boot by John Cronin 1/3/2013 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | typedef void * locale_t; 38 | 39 | /* 40 | * Convert a string to a long integer. 41 | * 42 | * Assumes that the upper and lower case 43 | * alphabets and digits are each contiguous. 44 | */ 45 | long 46 | strtol_l(const char * __restrict nptr, char ** __restrict endptr, int base, 47 | locale_t loc) 48 | { 49 | const char *s; 50 | unsigned long acc; 51 | char c; 52 | unsigned long cutoff; 53 | int neg, any, cutlim; 54 | 55 | (void)loc; 56 | /* 57 | * Skip white space and pick up leading +/- sign if any. 58 | * If base is 0, allow 0x for hex and 0 for octal, else 59 | * assume decimal; if base is already 16, allow 0x. 60 | */ 61 | s = nptr; 62 | do { 63 | c = *s++; 64 | } while (isspace((unsigned char)c)); 65 | if (c == '-') { 66 | neg = 1; 67 | c = *s++; 68 | } else { 69 | neg = 0; 70 | if (c == '+') 71 | c = *s++; 72 | } 73 | if ((base == 0 || base == 16) && 74 | c == '0' && (*s == 'x' || *s == 'X') && 75 | ((s[1] >= '0' && s[1] <= '9') || 76 | (s[1] >= 'A' && s[1] <= 'F') || 77 | (s[1] >= 'a' && s[1] <= 'f'))) { 78 | c = s[1]; 79 | s += 2; 80 | base = 16; 81 | } 82 | if (base == 0) 83 | base = c == '0' ? 8 : 10; 84 | acc = any = 0; 85 | if (base < 2 || base > 36) 86 | goto noconv; 87 | 88 | /* 89 | * Compute the cutoff value between legal numbers and illegal 90 | * numbers. That is the largest legal value, divided by the 91 | * base. An input number that is greater than this value, if 92 | * followed by a legal input character, is too big. One that 93 | * is equal to this value may be valid or not; the limit 94 | * between valid and invalid numbers is then based on the last 95 | * digit. For instance, if the range for longs is 96 | * [-2147483648..2147483647] and the input base is 10, 97 | * cutoff will be set to 214748364 and cutlim to either 98 | * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated 99 | * a value > 214748364, or equal but the next digit is > 7 (or 8), 100 | * the number is too big, and we will return a range error. 101 | * 102 | * Set 'any' if any `digits' consumed; make it negative to indicate 103 | * overflow. 104 | */ 105 | cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX 106 | : LONG_MAX; 107 | cutlim = cutoff % base; 108 | cutoff /= base; 109 | for ( ; ; c = *s++) { 110 | if (c >= '0' && c <= '9') 111 | c -= '0'; 112 | else if (c >= 'A' && c <= 'Z') 113 | c -= 'A' - 10; 114 | else if (c >= 'a' && c <= 'z') 115 | c -= 'a' - 10; 116 | else 117 | break; 118 | if (c >= base) 119 | break; 120 | if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 121 | any = -1; 122 | else { 123 | any = 1; 124 | acc *= base; 125 | acc += c; 126 | } 127 | } 128 | if (any < 0) { 129 | acc = neg ? LONG_MIN : LONG_MAX; 130 | errno = ERANGE; 131 | } else if (!any) { 132 | noconv: 133 | errno = EINVAL; 134 | } else if (neg) 135 | acc = -acc; 136 | if (endptr != NULL) 137 | *endptr = (char *)(any ? s - 1 : nptr); 138 | return (acc); 139 | } 140 | 141 | long 142 | strtol(const char * __restrict nptr, char ** __restrict endptr, int base) 143 | { 144 | return strtol_l(nptr, endptr, base, (void*)0); 145 | } 146 | 147 | -------------------------------------------------------------------------------- /strtoll.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: strtoll.c,v 1.7 2013/03/28 18:09:38 martynas Exp $ */ 2 | /*- 3 | * Copyright (c) 1992 The Regents of the University of California. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 3. Neither the name of the University nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY 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 | 31 | /* 32 | * Modified 21 May 2013 for rpi-boot by github.org/JamesC1 33 | * 34 | * Interestingly, longlong division pulls in a bunch of 35 | * exception-handling code. 36 | * Trying to rewrite to avoid doing it. 37 | */ 38 | 39 | /* 40 | #include 41 | */ 42 | 43 | #include "ctype.h" 44 | #include 45 | #include 46 | #include 47 | 48 | #ifdef STRTOLL_DEBUG 49 | #include 50 | #endif 51 | 52 | /* 53 | * Convert a string to a long long. 54 | * 55 | * Ignores `locale' stuff. Assumes that the upper and lower case 56 | * alphabets and digits are each contiguous. 57 | */ 58 | long long 59 | strtoll(const char *nptr, char **endptr, int base) 60 | { 61 | const char *s; 62 | unsigned long long acc; 63 | int c; 64 | int neg, any; 65 | 66 | /* 67 | * Skip white space and pick up leading +/- sign if any. 68 | * If base is 0, allow 0x for hex and 0 for octal, else 69 | * assume decimal; if base is already 16, allow 0x. 70 | */ 71 | s = nptr; 72 | do { 73 | c = (unsigned char) *s++; 74 | } while (isspace(c)); 75 | 76 | if (c == '-') { 77 | neg = 1; 78 | c = *s++; 79 | } else { 80 | neg = 0; 81 | if (c == '+') 82 | c = *s++; 83 | } 84 | 85 | if ((base == 0 || base == 16) && 86 | c == '0' && (*s == 'x' || *s == 'X')) { 87 | c = s[1]; 88 | s += 2; 89 | base = 16; 90 | } 91 | 92 | if (base == 0) 93 | base = c == '0' ? 8 : 10; 94 | 95 | /* 96 | * acc accumulates a positive number. 97 | * Overflow is when the correctly signed version of 98 | * that number has the wrong sign. 99 | */ 100 | 101 | for (acc = 0, any = 0;; c = (unsigned char) *s++) { 102 | if (isdigit(c)) 103 | c -= '0'; 104 | else if (isalpha(c)) 105 | c -= isupper(c) ? 'A' - 10 : 'a' - 10; 106 | else 107 | break; 108 | if (c >= base) 109 | break; 110 | if (any < 0) 111 | continue; 112 | any = 1; 113 | acc *= base; 114 | acc += c; 115 | #ifdef STRTOLL_DEBUG 116 | printf(" accumulator so far: %u(0x%x)", 117 | (unsigned long)acc, (unsigned long)acc); 118 | #endif 119 | if (neg) { 120 | if (0LL < (long long)(-acc)) 121 | { 122 | #ifdef STRTOLL_DEBUG 123 | printf(" OVERFLOW negative: %lld\n", 124 | (long long)(-acc)); 125 | #endif 126 | any = -1; 127 | acc = LLONG_MIN; 128 | errno = ERANGE; 129 | } 130 | } else { 131 | if (0LL > (long long)(acc)) 132 | { 133 | #ifdef STRTOLL_DEBUG 134 | printf(" OVERFLOW positive: %lld\n", 135 | (long long)(-acc)); 136 | #endif 137 | any = -1; 138 | acc = LLONG_MAX; 139 | errno = ERANGE; 140 | } 141 | } 142 | } 143 | if (endptr != 0) 144 | *endptr = (char *) (any ? s - 1 : nptr); 145 | if (neg) 146 | return (-acc); 147 | else 148 | return (acc); 149 | } 150 | 151 | -------------------------------------------------------------------------------- /test_kernel/Makefile: -------------------------------------------------------------------------------- 1 | ARM-CC ?= arm-none-eabi-gcc 2 | ARM-LD ?= arm-none-eabi-ld 3 | 4 | all: test.elf 5 | 6 | CFLAGS := -nostdlib -nostartfiles -ffreestanding -g -I.. -std=c99 7 | 8 | OBJS = loader.o main.o 9 | 10 | .PHONY: clean 11 | 12 | test.elf: $(OBJS) linker.ld 13 | $(ARM-CC) -nostdlib $(OBJS) -Wl,-T,linker.ld -Wl,-z,max-page-size=0x1000 -o $@ -lgcc 14 | 15 | clean: 16 | $(RM) -f $(OBJS) test.elf 17 | 18 | %.o: %.c Makefile 19 | $(ARM-CC) $(CFLAGS) -c $< -o $@ 20 | 21 | %.o: %.s Makefile 22 | $(ARM-CC) $(ASFLAGS) -c $< -o $@ 23 | 24 | -------------------------------------------------------------------------------- /test_kernel/boot/rpi-boot.cfg: -------------------------------------------------------------------------------- 1 | multiboot test.elf 2 | boot 3 | 4 | -------------------------------------------------------------------------------- /test_kernel/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY (loader) 2 | 3 | SECTIONS 4 | { 5 | . = 0x00100000; 6 | 7 | .text ALIGN(0x1000): 8 | { 9 | *(.text) 10 | } 11 | 12 | .rodata ALIGN(0x1000) : 13 | { 14 | *(.rodata*) 15 | } 16 | 17 | .data ALIGN (0x1000) : 18 | { 19 | *(.data) 20 | } 21 | 22 | .bss : 23 | { 24 | sbss = .; 25 | *(COMMON) 26 | *(.bss) 27 | ebss = .; 28 | } 29 | 30 | .comment (INFO) : 31 | { 32 | LONG(0xdeadbeef) 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /test_kernel/loader.s: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | .global loader 23 | 24 | .set ALIGN, 1<<0 25 | .set MEMINFO, 1<<1 26 | .set FLAGS, ALIGN | MEMINFO 27 | .set MAGIC, 0x1BADB002 28 | .set CHECKSUM, -(MAGIC + FLAGS) 29 | 30 | mboot_header: 31 | .long MAGIC 32 | .long FLAGS 33 | .long CHECKSUM 34 | 35 | .section .text 36 | 37 | stack_bottom: 38 | .skip 1024 39 | stack_top: 40 | .comm mbd, 4 41 | .comm magic, 4 42 | .comm m_type, 4 43 | .comm funcs, 4 44 | 45 | loader: 46 | ldr sp, =stack_top 47 | 48 | ldr r4, =kmain 49 | blx r4 50 | 51 | halt: 52 | wfe 53 | b halt 54 | 55 | -------------------------------------------------------------------------------- /test_kernel/main.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include "../multiboot.h" 24 | 25 | void kmain(uint32_t magic, multiboot_header_t *mbd, uint32_t m_type, 26 | struct multiboot_arm_functions *funcs) 27 | { 28 | funcs->clear(); 29 | funcs->printf("Welcome to the test kernel\n"); 30 | funcs->printf("Multiboot magic: %x\n", magic); 31 | funcs->printf("Running on machine type: %x\n", m_type); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /timer.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include "timer.h" 23 | #include "mmio.h" 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #define TIMER_BASE 0x20003000 30 | #define TIMER_CLO 0x4 31 | 32 | static uint32_t timer_base = TIMER_BASE; 33 | 34 | void timer_set_base(uint32_t base) 35 | { 36 | timer_base = base; 37 | } 38 | 39 | int usleep(useconds_t usec) 40 | { 41 | struct timer_wait tw = register_timer(usec); 42 | while(!compare_timer(tw)); 43 | return 0; 44 | } 45 | 46 | struct timer_wait register_timer(useconds_t usec) 47 | { 48 | struct timer_wait tw; 49 | tw.rollover = 0; 50 | tw.trigger_value = 0; 51 | 52 | if(usec < 0) 53 | { 54 | errno = EINVAL; 55 | return tw; 56 | } 57 | uint32_t cur_timer = mmio_read(timer_base + TIMER_CLO); 58 | uint32_t trig = cur_timer + (uint32_t)usec; 59 | 60 | if(cur_timer == 0) 61 | trig = 0; 62 | 63 | tw.trigger_value = trig; 64 | if(trig > cur_timer) 65 | tw.rollover = 0; 66 | else 67 | tw.rollover = 1; 68 | return tw; 69 | } 70 | 71 | int compare_timer(struct timer_wait tw) 72 | { 73 | uint32_t cur_timer = mmio_read(timer_base + TIMER_CLO); 74 | 75 | if(tw.trigger_value == 0) 76 | return 1; 77 | 78 | if(cur_timer < tw.trigger_value) 79 | { 80 | if(tw.rollover) 81 | tw.rollover = 0; 82 | } 83 | else if(!tw.rollover) 84 | return 1; 85 | 86 | return 0; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /timer.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef TIMER_H 23 | #define TIMER_H 24 | 25 | #include 26 | #include 27 | 28 | typedef int useconds_t; 29 | 30 | struct timer_wait 31 | { 32 | uint32_t trigger_value; 33 | int rollover; 34 | }; 35 | 36 | int usleep(useconds_t usec); 37 | struct timer_wait register_timer(useconds_t usec); 38 | int compare_timer(struct timer_wait tw); 39 | 40 | #define TIMEOUT_WAIT(stop_if_true, usec) \ 41 | do { \ 42 | struct timer_wait tw = register_timer(usec); \ 43 | do \ 44 | { \ 45 | if(stop_if_true) \ 46 | break; \ 47 | } while(!compare_timer(tw)); \ 48 | } while(0); 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /uart.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include "mmio.h" 25 | #include "uart.h" 26 | #include "timer.h" 27 | 28 | #define GPIO_BASE 0x20200000 29 | #define GPPUD 0x94 30 | #define GPPUDCLK0 0x98 31 | #define UART0_BASE 0x20201000 32 | #define UART0_DR 0x00 33 | #define UART0_RSRECR 0x04 34 | #define UART0_FR 0x18 35 | #define UART0_ILPR 0x20 36 | #define UART0_IBRD 0x24 37 | #define UART0_FBRD 0x28 38 | #define UART0_LCRH 0x2C 39 | #define UART0_CR 0x30 40 | #define UART0_IFLS 0x34 41 | #define UART0_IMSC 0x38 42 | #define UART0_RIS 0x3C 43 | #define UART0_MIS 0x40 44 | #define UART0_ICR 0x44 45 | #define UART0_DMACR 0x48 46 | #define UART0_ITCR 0x80 47 | #define UART0_ITIP 0x84 48 | #define UART0_ITOP 0x88 49 | #define UART0_TDR 0x8C 50 | 51 | static uint32_t uart_base = UART0_BASE; 52 | static uint32_t gpio_base = GPIO_BASE; 53 | 54 | void uart_set_base(uint32_t base) 55 | { 56 | uart_base = base; 57 | } 58 | 59 | void gpio_set_base(uint32_t base) 60 | { 61 | gpio_base = base; 62 | } 63 | 64 | void uart_init() 65 | { 66 | // disable UART 67 | mmio_write(uart_base + UART0_CR, 0x0); 68 | 69 | // the following disables pullup/down for GPIO pins 14 and 15 70 | mmio_write(gpio_base + GPPUD, 0x0); 71 | usleep(150000); 72 | 73 | mmio_write(gpio_base + GPPUDCLK0, (1 << 14) | (1 << 15)); 74 | usleep(150000); 75 | 76 | mmio_write(gpio_base + GPPUDCLK0, 0x0); 77 | 78 | // clear interrupts 79 | mmio_write(uart_base + UART0_ICR, 0x7ff); 80 | 81 | // set baud rate - commented out therefore use default 82 | //mmio_write(uart_base + UART0_IBRD, 1); 83 | //mmio_write(uart_base + UART0_FBRD, 40); 84 | 85 | // 8 bit, no parity, 1 stop bit - commented out therefore use default 86 | //mmio_write(uart_base + UART0_LCRH, (1 << 4) | (1 << 5) | (1 << 6)); 87 | 88 | // interrupt mask 89 | mmio_write(uart_base + UART0_IMSC, (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | 90 | (1 << 8) | (1 << 9) | (1 << 10)); 91 | 92 | // enable device, transmit and receive 93 | mmio_write(uart_base + UART0_CR, (1 << 0) | (1 << 8) | (1 << 9)); 94 | } 95 | 96 | int uart_putc(int byte) 97 | { 98 | while(mmio_read(uart_base + UART0_FR) & (1 << 5)) 99 | usleep(2000); 100 | 101 | mmio_write(uart_base + UART0_DR, (uint8_t)(byte & 0xff)); 102 | 103 | if(byte == '\n') 104 | uart_putc('\r'); 105 | 106 | return byte; 107 | } 108 | 109 | int uart_getc() 110 | { 111 | while(mmio_read(uart_base + UART0_FR) & (1 << 4)) 112 | usleep(2000); 113 | return mmio_read(uart_base + UART0_DR) & 0xff; 114 | } 115 | 116 | int uart_getc_timeout(useconds_t timeout) 117 | { 118 | TIMEOUT_WAIT((mmio_read(uart_base + UART0_FR) & (1 << 4)) == 0, timeout); 119 | if((mmio_read(uart_base + UART0_FR) & (1 << 4)) == 0) 120 | return mmio_read(uart_base + UART0_DR) & 0xff; 121 | else 122 | return -1; 123 | } 124 | 125 | void uart_puts(const char *str) 126 | { 127 | while(*str) 128 | uart_putc(*str++); 129 | } 130 | 131 | -------------------------------------------------------------------------------- /uart.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef UART_H 23 | #define UART_H 24 | 25 | #include 26 | #include "timer.h" 27 | 28 | void uart_init(); 29 | int uart_putc(int byte); 30 | void uart_puts(const char *str); 31 | int uart_getc(); 32 | int uart_getc_timeout(useconds_t timeout); 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /usb.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | /* This defines the basic usb structures and functions */ 23 | 24 | #ifndef USB_H 25 | #define USB_H 26 | 27 | #define USB_REQ_TYPE_CONTROL 0 28 | #define USB_REQ_TYPE_BULK 1 29 | #define USB_REQ_TYPE_INTERRUPT 2 30 | #define USB_REQ_TYPE_ISO 3 31 | 32 | #define USB_REQ_DIR_HD 0 33 | #define USB_REQ_DIR_DH 1 34 | 35 | struct usb_hcd; 36 | 37 | struct usb_request 38 | { 39 | struct usb_hcd *hcd; 40 | uint32_t pipe; 41 | 42 | int type; 43 | int direction; 44 | }; 45 | 46 | struct usb_hcd 47 | { 48 | char *driver_name; 49 | char *device_name; 50 | 51 | int (*send_req)(struct usb_hcd *, struct usb_request *); 52 | int (*reset)(struct usb_hcd *); 53 | }; 54 | 55 | 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef UTIL_H 23 | #define UTIL_H 24 | 25 | #include 26 | #include 27 | 28 | // Support for unaligned data access 29 | static inline void write_word(uint32_t val, uint8_t *buf, int offset) 30 | { 31 | buf[offset + 0] = val & 0xff; 32 | buf[offset + 1] = (val >> 8) & 0xff; 33 | buf[offset + 2] = (val >> 16) & 0xff; 34 | buf[offset + 3] = (val >> 24) & 0xff; 35 | } 36 | 37 | static inline void write_halfword(uint16_t val, uint8_t *buf, int offset) 38 | { 39 | buf[offset + 0] = val & 0xff; 40 | buf[offset + 1] = (val >> 8) & 0xff; 41 | } 42 | 43 | static inline void write_byte(uint8_t byte, uint8_t *buf, int offset) 44 | { 45 | buf[offset] = byte; 46 | } 47 | 48 | static inline uint32_t read_word(const uint8_t *buf, int offset) 49 | { 50 | uint32_t b0 = buf[offset + 0] & 0xff; 51 | uint32_t b1 = buf[offset + 1] & 0xff; 52 | uint32_t b2 = buf[offset + 2] & 0xff; 53 | uint32_t b3 = buf[offset + 3] & 0xff; 54 | 55 | return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); 56 | } 57 | 58 | static inline uint32_t read_wordbe(const uint8_t *buf, int offset) 59 | { 60 | uint32_t b0 = buf[offset + 0] & 0xff; 61 | uint32_t b1 = buf[offset + 1] & 0xff; 62 | uint32_t b2 = buf[offset + 2] & 0xff; 63 | uint32_t b3 = buf[offset + 3] & 0xff; 64 | 65 | return b3 | (b2 << 8) | (b1 << 16) | (b0 << 24); 66 | } 67 | 68 | static inline uint16_t read_halfword(uint8_t *buf, int offset) 69 | { 70 | uint16_t b0 = buf[offset + 0] & 0xff; 71 | uint16_t b1 = buf[offset + 1] & 0xff; 72 | 73 | return b0 | (b1 << 8); 74 | } 75 | 76 | static inline uint8_t read_byte(uint8_t *buf, int offset) 77 | { 78 | return buf[offset]; 79 | } 80 | 81 | void *quick_memcpy(void *dest, void *src, size_t n); 82 | 83 | // A faster memcpy if 16-byte alignment is assured 84 | static inline void *qmemcpy(void *dest, void *src, size_t n) 85 | { 86 | // Can only use quick_memcpy if dest, src and n are multiples 87 | // of 16 88 | if((((uintptr_t)dest & 0xf) == 0) && (((uintptr_t)src & 0xf) == 0) && 89 | ((n & 0xf) == 0)) 90 | return quick_memcpy(dest, src, n); 91 | else 92 | return memcpy(dest, src, n); 93 | } 94 | 95 | uintptr_t alloc_buf(size_t size); 96 | 97 | // Support for BE to LE conversion 98 | #ifdef __GNUC__ 99 | #define byte_swap __builtin_bswap32 100 | #else 101 | static inline uint32_t byte_swap(uint32_t in) 102 | { 103 | uint32_t b0 = in & 0xff; 104 | uint32_t b1 = (in >> 8) & 0xff; 105 | uint32_t b2 = (in >> 16) & 0xff; 106 | uint32_t b3 = (in >> 24) & 0xff; 107 | uint32_t ret = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; 108 | return ret; 109 | } 110 | #endif // __GNUC__ 111 | 112 | #endif 113 | 114 | -------------------------------------------------------------------------------- /vfs.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 by John Cronin 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #ifndef VFS_H 23 | #define VFS_H 24 | 25 | struct vfs_file; 26 | 27 | #include "dirent.h" 28 | #include "multiboot.h" 29 | 30 | #ifndef EOF 31 | #define EOF 0xff 32 | #endif 33 | 34 | #ifdef FILE 35 | #undef FILE 36 | #endif 37 | #define FILE struct vfs_file 38 | 39 | #include "fs.h" 40 | 41 | struct vfs_entry 42 | { 43 | char *device_name; 44 | struct fs *fs; 45 | struct vfs_entry *next; 46 | }; 47 | 48 | #define VFS_MODE_R 1 49 | #define VFS_MODE_W 2 50 | #define VFS_MODE_RW 3 51 | #define VFS_MODE_APPEND 4 52 | #define VFS_MODE_CREATE 8 53 | 54 | #define VFS_FLAGS_EOF 1 55 | #define VFS_FLAGS_ERROR 2 56 | 57 | struct vfs_file 58 | { 59 | struct fs *fs; 60 | long pos; 61 | int mode; 62 | void *opaque; 63 | long len; 64 | int flags; 65 | int (*fflush_cb)(FILE *f); 66 | }; 67 | 68 | int fseek(FILE *stream, long offset, int whence); 69 | long ftell(FILE *stream); 70 | long fsize(FILE *stream); 71 | int feof(FILE *stream); 72 | int ferror(FILE *stream); 73 | int fflush(FILE *stream); 74 | void rewind(FILE *stream); 75 | 76 | int vfs_register(struct fs *fs); 77 | void vfs_list_devices(); 78 | char **vfs_get_device_list(); 79 | int vfs_set_default(char *dev_name); 80 | char *vfs_get_default(); 81 | 82 | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 83 | size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream); 84 | FILE *fopen(const char *path, const char *mode); 85 | int fclose(FILE *fp); 86 | DIR *opendir(const char *name); 87 | struct dirent *readdir(DIR *dirp); 88 | int closedir(DIR *dirp); 89 | 90 | #endif 91 | 92 | --------------------------------------------------------------------------------