├── lodepng.c ├── lodepng.h ├── .obj └── fatfs │ └── .keep ├── mklogo ├── .gitignore ├── lodepng.c ├── lodepng.h ├── Makefile └── main.c ├── lstrender ├── lodepng.c ├── lodepng.h ├── .obj │ └── shared │ │ └── .keep ├── .gitignore ├── virtual_console.h ├── log_compat.h ├── Makefile ├── virtual_console.c └── lstrender.c ├── docs ├── _config.yml ├── tux-wii.png ├── gumboot-logo.png ├── gumboot-default-menu.png └── index.md ├── font.c ├── logo.png ├── TODO ├── .gitmodules ├── utils.h ├── .gitignore ├── atoi.h ├── log.h ├── time.h ├── README.md ├── menu.h ├── types_compat.h ├── gecko.h ├── raster.h ├── browse.h ├── broadway.mk ├── atoi.c ├── powerpc_elf.h ├── nandfs.h ├── exception_2200.S ├── fatfs ├── 00readme.txt ├── integer.h ├── diskio.h ├── ffsystem.c ├── 00history.txt ├── ffconf.h └── ff.h ├── types.h ├── powerpc.c ├── console.h ├── utils.c ├── string.h ├── sync.c ├── menu_render.h ├── printf.h ├── mini.ld ├── elf.h ├── lodepng-gumboot.patch ├── log.c ├── Makefile ├── config.h ├── console_common.c ├── time.c ├── gumboot.lst ├── common.mk ├── input.h ├── old_diskio.h ├── exception.c ├── hollywood.h ├── console_common.h ├── powerpc.h ├── video_low.h ├── menu.c ├── old_diskio.c ├── realmode.S ├── string.c ├── mini_ipc.h ├── input.c ├── browse.c ├── mini_ipc.c ├── diskio.c ├── ipc.h ├── gecko.c ├── menu_render.c ├── main.c ├── ipc.c ├── nandfs.c ├── powerpc_elf.c ├── crt0.S ├── console.c └── video_low.c /lodepng.c: -------------------------------------------------------------------------------- 1 | lodepng/lodepng.cpp -------------------------------------------------------------------------------- /lodepng.h: -------------------------------------------------------------------------------- 1 | lodepng/lodepng.h -------------------------------------------------------------------------------- /.obj/fatfs/.keep: -------------------------------------------------------------------------------- 1 | # keep this file 2 | -------------------------------------------------------------------------------- /mklogo/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | mklogo 3 | -------------------------------------------------------------------------------- /mklogo/lodepng.c: -------------------------------------------------------------------------------- 1 | ../lodepng/lodepng.cpp -------------------------------------------------------------------------------- /mklogo/lodepng.h: -------------------------------------------------------------------------------- 1 | ../lodepng/lodepng.h -------------------------------------------------------------------------------- /lstrender/lodepng.c: -------------------------------------------------------------------------------- 1 | ../lodepng/lodepng.cpp -------------------------------------------------------------------------------- /lstrender/lodepng.h: -------------------------------------------------------------------------------- 1 | ../lodepng/lodepng.h -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker 2 | -------------------------------------------------------------------------------- /lstrender/.obj/shared/.keep: -------------------------------------------------------------------------------- 1 | # keep this file 2 | -------------------------------------------------------------------------------- /font.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neagix/gumboot/HEAD/font.c -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neagix/gumboot/HEAD/logo.png -------------------------------------------------------------------------------- /lstrender/.gitignore: -------------------------------------------------------------------------------- 1 | .obj/*.o 2 | .obj/shared/*.o 3 | lstrender 4 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 2 | * ext4 support? https://git.pengutronix.de/cgit/barebox/tree/fs/ext4 3 | -------------------------------------------------------------------------------- /docs/tux-wii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neagix/gumboot/HEAD/docs/tux-wii.png -------------------------------------------------------------------------------- /docs/gumboot-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neagix/gumboot/HEAD/docs/gumboot-logo.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lodepng"] 2 | path = lodepng 3 | url = https://github.com/lvandeve/lodepng 4 | -------------------------------------------------------------------------------- /docs/gumboot-default-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neagix/gumboot/HEAD/docs/gumboot-default-menu.png -------------------------------------------------------------------------------- /utils.h: -------------------------------------------------------------------------------- 1 | 2 | #include "types.h" 3 | 4 | char *load_file(const char *fname, u32 max_allowed, u32 *read); 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .obj/*.o 2 | .obj/fatfs/*.o 3 | .deps/ 4 | gumboot.elf 5 | gumboot.elf.map 6 | logo.c 7 | logo.h 8 | -------------------------------------------------------------------------------- /atoi.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | int atoi_base(register char *s, register unsigned int base, size_t *parsed); 5 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | 2 | #include "gecko.h" 3 | #include "console.h" 4 | 5 | int log_printf(const char *fmt, ...); 6 | int log_init_bb(void); 7 | void log_flush_bb(void); 8 | void log_free_bb(void); 9 | -------------------------------------------------------------------------------- /time.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _TIME_H 3 | #define _TIME_H 4 | 5 | // Time. 6 | 7 | #include "types.h" 8 | 9 | void usleep(u32 us); 10 | u64 mftb(void); 11 | u64 mftb_usec(void); 12 | void sleep(u32 s); 13 | 14 | #endif // _TIME_H 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gumboot 2 | 3 | See [docs/index.md](docs/index.md) or https://neagix.github.io/gumboot/ 4 | 5 | # Building 6 | 7 | ``` 8 | WIIDEV=$HOME/projects/wiidev make 9 | ``` 10 | 11 | # License 12 | 13 | [GNU/GPL v2](COPYING) 14 | -------------------------------------------------------------------------------- /menu.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MENU_H 3 | #define _MENU_H 4 | 5 | #include "console.h" 6 | #include "config.h" 7 | #include "types.h" 8 | 9 | void menu_up(void); 10 | void menu_down(void); 11 | int menu_activate(void); 12 | 13 | #endif // _MENU_H 14 | -------------------------------------------------------------------------------- /types_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef __TYPES_COMPAT_H__ 2 | #define __TYPES_COMPAT_H__ 3 | 4 | #include 5 | /*typedef unsigned int size_t; 6 | typedef signed int ssize_t;*/ 7 | 8 | #define NULL ((void *)0) 9 | 10 | #endif // __TYPES_COMPAT_H__ 11 | -------------------------------------------------------------------------------- /gecko.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef GECKO_H 3 | #define GECKO_H 4 | 5 | #include "types.h" 6 | 7 | extern int gecko_console_enabled; 8 | 9 | void gecko_init(void); 10 | int gecko_printf(const char *fmt, ...); 11 | int gecko_sendbuffer(const void *buffer, u32 size); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /raster.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __RASTER_H 3 | #define __RASTER_H 4 | 5 | typedef struct { 6 | unsigned width, height; 7 | unsigned char *pixels; 8 | } raster; 9 | 10 | #define png_to_raster(png, pngsize, rst) lodepng_decode32(&rst.pixels, &rst.width, &rst.height, png, pngsize) 11 | 12 | #endif // __RASTER_H 13 | -------------------------------------------------------------------------------- /lstrender/virtual_console.h: -------------------------------------------------------------------------------- 1 | 2 | #include "../config.h" 3 | #include "../console_common.h" 4 | 5 | void gfx_clear(int x, int y, int w, int h, rgb c); 6 | void gfx_draw_char(int dx, int dy, unsigned char c); 7 | 8 | void select_font(int font); 9 | 10 | extern unsigned char *vfb; 11 | extern unsigned vfb_stride; 12 | -------------------------------------------------------------------------------- /lstrender/log_compat.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | static void log_printf(const char *fmt, ...) 6 | { 7 | va_list args; 8 | va_start(args, fmt); 9 | vfprintf(stderr, fmt, args); 10 | va_end(args); 11 | } 12 | 13 | /*#define log_init_bb 14 | #define log_flush_bb 15 | #define log_free_bb 16 | */ 17 | -------------------------------------------------------------------------------- /browse.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __BROWSE_H 3 | #define __BROWSE_H 4 | 5 | #include "menu_render.h" 6 | 7 | int menu_browse(); 8 | int menu_browse_activate(void); 9 | 10 | extern char browse_current_path[4096]; 11 | extern char *browse_menu_entries[CONSOLE_LINES-HELP_LINES-HEAD_LINES-2]; 12 | extern int browse_menu_entries_count; 13 | 14 | #endif // __BROWSE_H 15 | -------------------------------------------------------------------------------- /mklogo/Makefile: -------------------------------------------------------------------------------- 1 | DEFINES = -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS -DLODEPNG_NO_COMPILE_CPP 2 | 3 | OBJS = lodepng.o main.o 4 | 5 | TARGET = mklogo 6 | 7 | $(TARGET): $(OBJS) 8 | @echo " LINK $@" 9 | $(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ 10 | 11 | %.o: %.c 12 | @echo " COMPILE $<" 13 | $(CC) $(CFLAGS) $(DEFINES) -c $< -o $@ 14 | 15 | clean: 16 | rm -f *.o 17 | -------------------------------------------------------------------------------- /broadway.mk: -------------------------------------------------------------------------------- 1 | ifeq ($(strip $(WIIDEV)),) 2 | $(error "Set WIIDEV in your environment.") 3 | endif 4 | 5 | PREFIX = $(WIIDEV)/bin/powerpc-elf- 6 | 7 | CFLAGS = -mcpu=750 -mpaired -m32 -mhard-float -mno-eabi -mno-sdata 8 | CFLAGS += -ffreestanding -ffunction-sections 9 | CFLAGS += -Wall -Wextra -Os -pipe 10 | ASFLAGS = 11 | LDFLAGS = -mcpu=750 -m32 -n -nostartfiles -nodefaultlibs -Wl,-gc-sections 12 | 13 | -------------------------------------------------------------------------------- /atoi.c: -------------------------------------------------------------------------------- 1 | 2 | #include "atoi.h" 3 | 4 | int atoi_base(register char *s, register unsigned int base, size_t *parsed) { 5 | register int result = 0; 6 | register unsigned int digit; 7 | 8 | for (*parsed = 0; ; s++) { 9 | digit = *s - '0'; 10 | if (digit > (base-1)) { 11 | // invalid digit 12 | break; 13 | } 14 | result = (base*result) + digit; 15 | (*parsed)++; 16 | } 17 | 18 | return result; 19 | } 20 | -------------------------------------------------------------------------------- /lstrender/Makefile: -------------------------------------------------------------------------------- 1 | OBJDIR:=.obj 2 | 3 | OBJS = $(OBJDIR)/lodepng.o $(OBJDIR)/lstrender.o $(OBJDIR)/shared/config.o $(OBJDIR)/shared/atoi.o $(OBJDIR)/shared/menu_render.o \ 4 | $(OBJDIR)/virtual_console.o $(OBJDIR)/shared/console_common.o $(OBJDIR)/shared/font.o $(OBJDIR)/shared/logo.o 5 | 6 | TARGET = lstrender 7 | 8 | $(TARGET): $(OBJS) 9 | @echo " LINK $@" 10 | $(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ 11 | 12 | $(OBJDIR)/%.o: %.c 13 | @echo " COMPILE $<" 14 | $(CC) $(CFLAGS) $(DEFINES) -c $< -o $@ 15 | 16 | $(OBJDIR)/shared/%.o: ../%.c 17 | @echo " COMPILE $<" 18 | $(CC) $(CFLAGS) $(DEFINES) -c $< -o $@ 19 | 20 | clean: 21 | rm -f $(OBJS) 22 | -------------------------------------------------------------------------------- /powerpc_elf.h: -------------------------------------------------------------------------------- 1 | /* 2 | mini - a Free Software replacement for the Nintendo/BroadOn IOS. 3 | PowerPC ELF file loading 4 | 5 | Copyright (C) 2008, 2009 Hector Martin "marcan" 6 | Copyright (C) 2009 Andre Heider "dhewg" 7 | 8 | # This code is licensed to you under the terms of the GNU GPL, version 2; 9 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 10 | */ 11 | 12 | #ifndef __POWERPC_ELF_H__ 13 | #define __POWERPC_ELF_H__ 14 | 15 | int is_valid_elf(const char *path); 16 | int powerpc_boot_file(const char *path, const char *args); 17 | int try_boot_file(char *kernel_fn, const char *args); 18 | 19 | #endif 20 | 21 | -------------------------------------------------------------------------------- /nandfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2008, 2009 Sven Peter 6 | 7 | # This code is licensed to you under the terms of the GNU GPL, version 2; 8 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 9 | */ 10 | 11 | #ifndef __NANDFS_H__ 12 | #define __NANDFS_H__ 13 | 14 | #define NANDFS_NAME_LEN 12 15 | 16 | #define NANDFS_SEEK_SET 0 17 | #define NANDFS_SEEK_CUR 1 18 | #define NANDFS_SEEK_END 2 19 | 20 | struct nandfs_fp { 21 | s16 first_cluster; 22 | s32 cur_cluster; 23 | u32 size; 24 | u32 offset; 25 | }; 26 | 27 | s32 nandfs_initialize(void); 28 | u32 nandfs_get_usage(void); 29 | 30 | s32 nandfs_open(struct nandfs_fp *fp, const char *path); 31 | s32 nandfs_read(void *ptr, u32 size, u32 nmemb, struct nandfs_fp *fp); 32 | s32 nandfs_seek(struct nandfs_fp *fp, s32 offset, u32 whence); 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /exception_2200.S: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2008 Segher Boessenkool 6 | 7 | # This code is licensed to you under the terms of the GNU GPL, version 2; 8 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 9 | */ 10 | 11 | .globl exception_2200_start, exception_2200_end 12 | 13 | exception_2200_start: 14 | # store all interesting regs 15 | mfcr 0 ; stw 0,0x2080(0) 16 | mfxer 0 ; stw 0,0x2084(0) 17 | mflr 0 ; stw 0,0x2088(0) 18 | mfctr 0 ; stw 0,0x208c(0) 19 | mfsrr0 0 ; stw 0,0x2090(0) 20 | mfsrr1 0 ; stw 0,0x2094(0) 21 | mfdar 0 ; stw 0,0x2098(0) 22 | mfdsisr 0 ; stw 0,0x209c(0) 23 | 24 | # switch on FP, DR, IR 25 | mfmsr 0 ; ori 0,0,0x2030 ; mtsrr1 0 26 | 27 | # go to C handler 28 | lis 0,exception_handler@h ; ori 0,0,exception_handler@l ; mtsrr0 0 29 | rfi 30 | exception_2200_end: 31 | 32 | -------------------------------------------------------------------------------- /fatfs/00readme.txt: -------------------------------------------------------------------------------- 1 | FatFs Module Source Files R0.13 2 | 3 | 4 | FILES 5 | 6 | 00readme.txt This file. 7 | 00history.txt Revision history. 8 | ff.c FatFs module. 9 | ffconf.h Configuration file of FatFs module. 10 | ff.h Common include file for FatFs and application module. 11 | diskio.h Common include file for FatFs and disk I/O module. 12 | diskio.c An example of glue function to attach existing disk I/O module to FatFs. 13 | integer.h Integer type definitions for FatFs. 14 | ffunicode.c Optional Unicode utility functions. 15 | ffsystem.c An example of optional O/S related functions. 16 | 17 | 18 | Low level disk I/O module is not included in this archive because the FatFs 19 | module is only a generic file system layer and it does not depend on any specific 20 | storage device. You need to provide a low level disk I/O module written to 21 | control the storage device that attached to the target system. 22 | 23 | -------------------------------------------------------------------------------- /fatfs/integer.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------*/ 2 | /* Integer type definitions for FatFs module */ 3 | /*-------------------------------------------*/ 4 | 5 | #ifndef FF_INTEGER 6 | #define FF_INTEGER 7 | 8 | #ifdef _WIN32 /* FatFs development platform */ 9 | 10 | #include 11 | #include 12 | typedef unsigned __int64 QWORD; 13 | 14 | 15 | #else /* Embedded platform */ 16 | 17 | /* These types MUST be 16-bit or 32-bit */ 18 | typedef int INT; 19 | typedef unsigned int UINT; 20 | 21 | /* This type MUST be 8-bit */ 22 | typedef unsigned char BYTE; 23 | 24 | /* These types MUST be 16-bit */ 25 | typedef short SHORT; 26 | typedef unsigned short WORD; 27 | typedef unsigned short WCHAR; 28 | 29 | /* These types MUST be 32-bit */ 30 | typedef long LONG; 31 | typedef unsigned long DWORD; 32 | 33 | /* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */ 34 | typedef unsigned long long QWORD; 35 | 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | # This code is licensed to you under the terms of the GNU GPL, version 2; 6 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 7 | */ 8 | 9 | #ifndef __TYPES_H__ 10 | #define __TYPES_H__ 11 | 12 | typedef unsigned char u8; 13 | typedef unsigned short u16; 14 | typedef unsigned int u32; 15 | typedef unsigned long long u64; 16 | 17 | typedef signed char s8; 18 | typedef signed short s16; 19 | typedef signed int s32; 20 | typedef signed long long s64; 21 | 22 | typedef volatile unsigned char vu8; 23 | typedef volatile unsigned short vu16; 24 | typedef volatile unsigned int vu32; 25 | typedef volatile unsigned long long vu64; 26 | 27 | typedef volatile signed char vs8; 28 | typedef volatile signed short vs16; 29 | typedef volatile signed int vs32; 30 | typedef volatile signed long long vs64; 31 | 32 | /* Boolean type */ 33 | //typedef enum { FALSE = 0, TRUE } BOOL; 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /powerpc.c: -------------------------------------------------------------------------------- 1 | 2 | #include "powerpc.h" 3 | #include "ipc.h" 4 | #include "time.h" 5 | 6 | void dsp_reset(void) 7 | { 8 | write16(0x0c00500a, read16(0x0c00500a) & ~0x01f8); 9 | write16(0x0c00500a, read16(0x0c00500a) | 0x0010); 10 | write16(0x0c005036, 0); 11 | } 12 | 13 | void powerpc_hang(void) 14 | { 15 | ipc_sys_clear32(HW_RESETS, 0x30); 16 | usleep(100); 17 | ipc_sys_set32(HW_RESETS, 0x20); 18 | usleep(100); 19 | } 20 | 21 | void powerpc_reset(void) 22 | { 23 | // enable the broadway IPC interrupt 24 | write32(HW_PPCIRQMASK, (1<<30)); 25 | ipc_sys_clear32(HW_RESETS, 0x30); 26 | usleep(100); 27 | ipc_sys_set32(HW_RESETS, 0x20); 28 | usleep(100); 29 | ipc_sys_set32(HW_RESETS, 0x10); 30 | usleep(100000); 31 | ipc_sys_set32(HW_EXICTRL, EXICTRL_ENABLE_EXI); 32 | } 33 | 34 | void powerpc_poweroff() { 35 | /* make sure that the poweroff GPIO is configured as output */ 36 | ipc_sys_set32(HW_GPIO1DIR, HW_GPIO_SHUTDOWN); 37 | 38 | /* drive the poweroff GPIO high */ 39 | ipc_sys_set32(HW_GPIO1OUT, HW_GPIO_SHUTDOWN); 40 | } 41 | -------------------------------------------------------------------------------- /console.h: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2009 bLAStY 6 | Copyright (C) 2009 John Kelley 7 | 8 | # This code is licensed to you under the terms of the GNU GPL, version 2; 9 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 10 | */ 11 | 12 | #ifndef __CONSOLE_H__ 13 | #define __CONSOLE_H__ 14 | 15 | #include "types.h" 16 | #include "types_compat.h" 17 | #include "config.h" 18 | #include "console_common.h" 19 | 20 | int gfx_printf(const char *fmt, ...); 21 | void init_fb(int vmode); 22 | void free_font(int font); 23 | void init_font(int font); 24 | void gfx_print(const char *str, size_t len); 25 | void gfx_clear(int x, int y, int w, int h, rgb c); 26 | u32 *get_xfb(void); 27 | void clear_fb(rgb fill_rgbc); 28 | 29 | void console_move(int x, int y); 30 | void console_set_blinker(int status); 31 | 32 | void select_font(int font); 33 | 34 | extern int gfx_console_init; 35 | 36 | extern rgb black; 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /utils.c: -------------------------------------------------------------------------------- 1 | 2 | #include "malloc.h" 3 | #include "types.h" 4 | #include "fatfs/ff.h" 5 | #include "log.h" 6 | 7 | void *load_file(const char *fname, u32 max_allowed, u32 *read) { 8 | FRESULT res; 9 | FIL fd; 10 | FILINFO stat; 11 | 12 | res = f_stat(fname, &stat); 13 | if (res != FR_OK) { 14 | log_printf("failed to stat %s: %d\n", fname, res); 15 | return NULL; 16 | } 17 | 18 | res = f_open(&fd, fname, FA_READ); 19 | if (res != FR_OK) { 20 | log_printf("failed to open %s: %d\n", fname, res); 21 | return NULL; 22 | } 23 | 24 | DWORD fsize = stat.fsize; 25 | if (fsize > max_allowed) { 26 | fsize = max_allowed; 27 | log_printf("truncating %s to %d bytes\n", fname, fsize); 28 | } 29 | void *mem = malloc(fsize); 30 | if (!mem) { 31 | log_printf("failed to allocate %d bytes\n", fsize); 32 | return NULL; 33 | } 34 | 35 | res = f_read(&fd, mem, fsize, read); 36 | if (res != FR_OK) { 37 | log_printf("failed to read %s: %d\n", fname, res); 38 | free(mem); 39 | f_close(&fd); 40 | return NULL; 41 | } 42 | f_close(&fd); 43 | 44 | return mem; 45 | } 46 | -------------------------------------------------------------------------------- /string.h: -------------------------------------------------------------------------------- 1 | /* string.c -- standard C string-manipulation functions. 2 | 3 | Copyright (C) 2008 Segher Boessenkool 4 | Copyright (C) 2009 Haxx Enterprises 5 | 6 | # This code is licensed to you under the terms of the GNU GPL, version 2; 7 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 8 | */ 9 | 10 | #ifndef _STRING_H 11 | #define _STRING_H 12 | 13 | #include "types.h" 14 | #include "types_compat.h" 15 | 16 | size_t strlen(const char *); 17 | size_t strnlen(const char *, size_t); 18 | void *memset(void *, int, size_t); 19 | void *memcpy(void *, const void *, size_t); 20 | int memcmp(const void *, const void *, size_t); 21 | int strcmp(const char *, const char *); 22 | int strncmp(const char *, const char *, size_t); 23 | size_t strlcpy(char *, const char *, size_t); 24 | size_t strlcat(char *, const char *, size_t); 25 | char *strcat(const char *, const char *); 26 | char *strchr(const char *, char); 27 | size_t strspn(const char *, const char *); 28 | size_t strcspn(const char *, const char *); 29 | char *strdup(const char *); 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /sync.c: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2008 Segher Boessenkool 6 | 7 | # This code is licensed to you under the terms of the GNU GPL, version 2; 8 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 9 | */ 10 | 11 | #include "powerpc.h" 12 | 13 | void sync_before_read(void *p, u32 len) 14 | { 15 | u32 a, b; 16 | 17 | a = (u32)p & ~0x1f; 18 | b = ((u32)p + len + 0x1f) & ~0x1f; 19 | 20 | for ( ; a < b; a += 32) 21 | asm("dcbi 0,%0" : : "b"(a)); 22 | 23 | asm("sync ; isync"); 24 | } 25 | 26 | void sync_after_write(const void *p, u32 len) 27 | { 28 | u32 a, b; 29 | 30 | a = (u32)p & ~0x1f; 31 | b = ((u32)p + len + 0x1f) & ~0x1f; 32 | 33 | for ( ; a < b; a += 32) 34 | asm("dcbst 0,%0" : : "b"(a)); 35 | 36 | asm("sync ; isync"); 37 | } 38 | 39 | void sync_before_exec(const void *p, u32 len) 40 | { 41 | u32 a, b; 42 | 43 | a = (u32)p & ~0x1f; 44 | b = ((u32)p + len + 0x1f) & ~0x1f; 45 | 46 | for ( ; a < b; a += 32) 47 | asm("dcbst 0,%0 ; sync ; icbi 0,%0" : : "b"(a)); 48 | 49 | asm("sync ; isync"); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /menu_render.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MENU_RENDER_H 3 | #define _MENU_RENDER_H 4 | 5 | #include "types.h" 6 | #include "config.h" 7 | #include "logo.h" 8 | 9 | #ifdef GUMBOOT 10 | #include "console.h" 11 | #include "string.h" 12 | #include "printf.h" 13 | #else 14 | #include "console_common.h" 15 | #include 16 | #include 17 | 18 | #include "lstrender/virtual_console.h" 19 | #endif 20 | 21 | #define GUMBOOT_VERSION "0.7" 22 | 23 | #define HELP_LINES 5 24 | #define HEAD_LINES 3 25 | #define BOX_H (CONSOLE_LINES-HEAD_LINES-HELP_LINES) 26 | #define LOGO_COLUMNS (GUMBOOT_LOGO_WIDTH/CONSOLE_CHAR_WIDTH + (GUMBOOT_LOGO_WIDTH % CONSOLE_CHAR_WIDTH != 0)) 27 | 28 | extern int menu_selection, old_menu_selection; 29 | 30 | void draw_box_at(int x, int y, int w, int h); 31 | void menu_draw_head_and_box(u16 mini_version_major, u16 mini_version_minor); 32 | void menu_draw_entries_and_help(void); 33 | void menu_clear_entries(void); 34 | void menu_init(raster *splash); 35 | 36 | void menu_update_timeout(int seconds); 37 | void menu_clear_timeout(void); 38 | void menu_draw_timeout(int seconds); 39 | 40 | extern const char *timeout_prompt, *timeout_prompt_term; 41 | 42 | #endif // _MENU_RENDER_H 43 | -------------------------------------------------------------------------------- /printf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995 Patrick Powell. 3 | * 4 | * This code is based on code written by Patrick Powell . 5 | * It may be used for any purpose as long as this notice remains intact on all 6 | * source code distributions. 7 | */ 8 | 9 | /* 10 | * Copyright (c) 2008 Holger Weiss. 11 | * 12 | * This version of the code is maintained by Holger Weiss . 13 | * My changes to the code may freely be used, modified and/or redistributed for 14 | * any purpose. It would be nice if additions and fixes to this file (including 15 | * trivial code cleanups) would be sent back in order to let me include them in 16 | * the version available at . 17 | * However, this is not a requirement for using or redistributing (possibly 18 | * modified) versions of this file, nor is leaving this notice intact mandatory. 19 | */ 20 | #ifndef __VSPRINTF_H__ 21 | #define __VSPRINTF_H__ 22 | 23 | #include 24 | #include "types_compat.h" 25 | 26 | int vsnprintf(char *str, size_t size, const char *format, va_list args); 27 | int snprintf(char *buffer, size_t size, const char *fmt, ...); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /mini.ld: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2009 Andre Heider "dhewg" 6 | 7 | # This code is licensed to you under the terms of the GNU GPL, version 2; 8 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 9 | */ 10 | 11 | OUTPUT_FORMAT("elf32-powerpc") 12 | OUTPUT_ARCH(powerpc:common) 13 | 14 | ENTRY(_realmode_vector) 15 | 16 | PHDRS { 17 | realmode PT_LOAD FLAGS(5); 18 | app PT_LOAD FLAGS(7); 19 | } 20 | 21 | SECTIONS { 22 | . = 0x00003400; 23 | 24 | .realmode : { *(.realmode) } :realmode = 0 25 | 26 | . = 0x80004000; 27 | 28 | .start : AT(ADDR(.start) & 0x3fffffff) { .obj/crt0.o(*) } :app = 0 29 | 30 | .text : { *(.text) *(.text.*) . = ALIGN(32); } 31 | 32 | .data : { *(.data) *(.data.*) . = ALIGN(32); } 33 | .sdata : { *(.sdata) *(.sdata.*) . = ALIGN(32); } 34 | .rodata : { *(.rodata) *(.rodata.*) . = ALIGN(32); } 35 | .stack : { 36 | _stack_top = .; 37 | . += 32768; 38 | _stack_bot = .; 39 | } 40 | 41 | . = ALIGN(32); 42 | 43 | __bss_start = .; 44 | .bss : { *(.bss) } 45 | .sbss : { *(.sbss) } 46 | __bss_end = .; 47 | 48 | . = ALIGN(0x10000); 49 | 50 | _sbrk_start = .; 51 | _sbrk_end = 0x816ffff0; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /elf.h: -------------------------------------------------------------------------------- 1 | /* 2 | mini - a Free Software replacement for the Nintendo/BroadOn IOS. 3 | ELF structures 4 | 5 | Copyright (C) 2008, 2009 Hector Martin "marcan" 6 | 7 | # This code is licensed to you under the terms of the GNU GPL, version 2; 8 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 9 | */ 10 | 11 | #ifndef __ELF_H__ 12 | #define __ELF_H__ 13 | 14 | #include "types.h" 15 | 16 | #define EI_NIDENT 16 17 | 18 | typedef struct { 19 | unsigned char e_ident[EI_NIDENT]; 20 | u16 e_type; 21 | u16 e_machine; 22 | u32 e_version; 23 | u32 e_entry; 24 | u32 e_phoff; 25 | u32 e_shoff; 26 | u32 e_flags; 27 | u16 e_ehsize; 28 | u16 e_phentsize; 29 | u16 e_phnum; 30 | u16 e_shentsize; 31 | u16 e_shnum; 32 | u16 e_shtrndx; 33 | } Elf32_Ehdr; 34 | 35 | typedef struct { 36 | u32 p_type; 37 | u32 p_offset; 38 | u32 p_vaddr; 39 | u32 p_paddr; 40 | u32 p_filesz; 41 | u32 p_memsz; 42 | u32 p_flags; 43 | u32 p_align; 44 | } Elf32_Phdr; 45 | 46 | #define PT_NULL 0 47 | #define PT_LOAD 1 48 | #define PT_DYNAMIC 2 49 | #define PT_INTERP 3 50 | #define PT_NOTE 4 51 | #define PT_SHLIB 5 52 | #define PT_PHDR 6 53 | 54 | typedef struct { 55 | u32 hdrsize; 56 | u32 loadersize; 57 | u32 elfsize; 58 | u32 argument; 59 | } ioshdr; 60 | 61 | #endif 62 | 63 | -------------------------------------------------------------------------------- /lodepng-gumboot.patch: -------------------------------------------------------------------------------- 1 | diff --git a/lodepng/lodepng.cpp b/lodepng/lodepng.cpp 2 | index bf237df..6af8ee8 100644 3 | --- a/lodepng/lodepng.cpp 4 | +++ b/lodepng/lodepng.cpp 5 | @@ -30,6 +30,8 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for 6 | 7 | #include "lodepng.h" 8 | 9 | +#ifndef GUMBOOT 10 | + 11 | #include 12 | #include 13 | #include 14 | @@ -39,6 +41,16 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for 15 | #pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ 16 | #endif /*_MSC_VER */ 17 | 18 | +#else 19 | + 20 | +#include "string.h" 21 | +#include "malloc.h" 22 | + 23 | +// emulate abs() 24 | +#define abs(a) ((a) < 0 ? (-(a)) : (a)) 25 | + 26 | +#endif // GUMBOOT 27 | + 28 | const char* LODEPNG_VERSION_STRING = "20161127"; 29 | 30 | /* 31 | diff --git a/lodepng/lodepng.h b/lodepng/lodepng.h 32 | index 8c634d2..527a3d6 100644 33 | --- a/lodepng/lodepng.h 34 | +++ b/lodepng/lodepng.h 35 | @@ -26,7 +26,11 @@ freely, subject to the following restrictions: 36 | #ifndef LODEPNG_H 37 | #define LODEPNG_H 38 | 39 | +#ifdef GUMBOOT 40 | +#include /*for size_t*/ 41 | +#else 42 | #include /*for size_t*/ 43 | +#endif 44 | 45 | extern const char* LODEPNG_VERSION_STRING; 46 | 47 | -------------------------------------------------------------------------------- /log.c: -------------------------------------------------------------------------------- 1 | 2 | #include "log.h" 3 | #include "printf.h" 4 | #include "console.h" 5 | #include "malloc.h" 6 | #include "string.h" 7 | 8 | #define MAX_BACKBUFFER_LEN ((CONSOLE_COLUMNS * CONSOLE_LINES * 2) / 3) 9 | 10 | char *back_buffer; 11 | int back_buffer_ptr = 0; 12 | 13 | int log_init_bb() { 14 | back_buffer = malloc(MAX_BACKBUFFER_LEN); 15 | if (!back_buffer) 16 | return -1; 17 | return 0; 18 | } 19 | 20 | void log_free_bb() { 21 | free(back_buffer); 22 | } 23 | 24 | int log_print(const char *buffer, int i) { 25 | if (gfx_console_init) { 26 | select_font(FONT_ERROR); 27 | gfx_print(buffer, i); 28 | } else { 29 | // accrete the back buffer 30 | if (i > (MAX_BACKBUFFER_LEN-back_buffer_ptr)) { 31 | // WE ARE DOOMED! NO MORE BACK BUFFER SPACE! OH NO..WHY.. 32 | return -1; 33 | } 34 | 35 | memcpy(back_buffer+back_buffer_ptr, buffer, i); 36 | back_buffer_ptr+=i; 37 | } 38 | 39 | if (gecko_console_enabled) 40 | return gecko_sendbuffer(buffer, i); 41 | 42 | return i; 43 | } 44 | 45 | int log_printf(const char *fmt, ...) { 46 | va_list args; 47 | char buffer[4096]; 48 | int i; 49 | 50 | va_start(args, fmt); 51 | i = vsnprintf(buffer, sizeof(buffer)-1, fmt, args); 52 | va_end(args); 53 | 54 | return log_print(buffer, i); 55 | } 56 | 57 | void log_flush_bb(void) { 58 | if (!back_buffer_ptr) 59 | return; 60 | 61 | log_print(back_buffer, back_buffer_ptr); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /mklogo/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "lodepng.h" 6 | 7 | int main(int argc, char **argv) 8 | { 9 | if (argc != 2) { 10 | fprintf(stderr, "Usage: mklogo logo.png\n"); 11 | return -1; 12 | } 13 | 14 | unsigned error; 15 | unsigned char* image; 16 | unsigned width, height; 17 | 18 | error = lodepng_decode32_file(&image, &width, &height, argv[1]); 19 | if(error) { 20 | printf("error %u: %s\n", error, lodepng_error_text(error)); 21 | return -2; 22 | } 23 | 24 | unsigned stride = width * 4; 25 | 26 | // generate header on standard error 27 | fprintf(stderr, "\n/* This file is automatically generated, DO NOT EDIT! */\n\n" 28 | "#define GUMBOOT_LOGO_WIDTH %d\n#define GUMBOOT_LOGO_HEIGHT %d\n\nextern unsigned char gumboot_logo_pixels[GUMBOOT_LOGO_WIDTH*GUMBOOT_LOGO_HEIGHT*4];\n", 29 | width, height); 30 | unsigned pixels_count = stride*height; 31 | 32 | // generate payload on standard input 33 | printf("\n/* This file is automatically generated, DO NOT EDIT! */\n\n" 34 | "unsigned char gumboot_logo_pixels[%d] = {\n", 35 | pixels_count); 36 | 37 | // start emitting the pixel data 38 | unsigned i = 0; 39 | printf("\t\t"); 40 | for(;i/dev/null; then exec patch -p1 < lodepng-gumboot.patch; fi 27 | make -C mklogo 28 | 29 | logo.c: logo.png mklogo/mklogo 30 | @echo " GENERATE $@" 31 | mklogo/mklogo logo.png >logo.c 2>logo.h 32 | 33 | upload: $(TARGET) 34 | @$(WIIDEV)/bin/bootmii -p $< 35 | 36 | .PHONY: upload mklogo/mklogo 37 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONFIG_H 2 | #define _CONFIG_H 3 | 4 | #include "types.h" 5 | 6 | #define MAX_SPLASH_SIZE 3*1024*1024 7 | #define MAX_CONFIG_ENTRIES 32 8 | #define MAX_LST_SIZE 16*1024 9 | #define DEFAULT_LST "gumboot/gumboot.lst" 10 | 11 | typedef union { 12 | struct __attribute__((__packed__)) { 13 | u8 r, g, b, a; 14 | } as_rgba; 15 | u32 as_u32; 16 | } rgb; 17 | 18 | typedef struct { 19 | char *title, 20 | *help_text, 21 | *root, 22 | *kernel, 23 | *kernel_args; 24 | u8 reboot, poweroff, browse; 25 | // FatFS does not support extended partitions 26 | // physical drive is always 0 because only one SD is supported 27 | // 'root' will include the drive/partition number 28 | } stanza; 29 | 30 | char *config_load(const char *fname, u32 *read); 31 | int config_load_from_buffer(char *cfg_data, u32 read); 32 | 33 | extern int config_timeout, config_default, config_entries_count, config_vmode, config_nomenu; 34 | extern stanza config_entries[MAX_CONFIG_ENTRIES]; 35 | 36 | #define rgbcmp(a,b) (a[0].as_u32 == b[0].as_u32) && (a[1].as_u32 == b[1].as_u32) 37 | 38 | extern rgb config_color_normal[2], 39 | config_color_highlight[2], 40 | config_color_helptext[2], 41 | config_color_heading[2]; 42 | 43 | extern rgb color_error[2]; 44 | extern rgb color_default[2]; 45 | extern char *config_splashimage; 46 | 47 | #define get_bgcolor(c) ((unsigned long)(c >> 32)) 48 | #define get_fgcolor(c) ((unsigned long)c) 49 | 50 | int config_open_fs(u8 part_no); 51 | 52 | #endif // _CONFIG_H 53 | -------------------------------------------------------------------------------- /console_common.c: -------------------------------------------------------------------------------- 1 | 2 | #include "console_common.h" 3 | 4 | #ifdef GUMBOOT 5 | #include "string.h" 6 | #include "printf.h" 7 | 8 | #else 9 | #include 10 | #include 11 | #include 12 | #endif 13 | 14 | char pf_buffer[4096]; 15 | 16 | void gfx_print_at(int x, int y, const char *str) { 17 | unsigned int i; 18 | 19 | int orig_x = CONSOLE_X_OFFSET + x * CONSOLE_CHAR_WIDTH; 20 | int dx = orig_x; 21 | 22 | for (i = 0; i < strlen(str); i++) { 23 | int dy = CONSOLE_Y_OFFSET + y * CONSOLE_ROW_HEIGHT; 24 | 25 | if (str[i] == '\n') { 26 | y++; 27 | dx = orig_x; 28 | continue; 29 | } 30 | 31 | gfx_draw_char(dx, dy, str[i]); 32 | dx += CONSOLE_CHAR_WIDTH; 33 | } 34 | } 35 | 36 | int gfx_printf_at(int x, int y, const char *fmt, ...) 37 | { 38 | va_list args; 39 | int i; 40 | 41 | va_start(args, fmt); 42 | i = vsnprintf(pf_buffer, sizeof(pf_buffer)-1, fmt, args); 43 | va_end(args); 44 | 45 | if (i > 0) { 46 | gfx_print_at(x, y, pf_buffer); 47 | } 48 | 49 | return i; 50 | } 51 | 52 | // apply (pre-multiplied) alpha blending 53 | // https://www.ocf.berkeley.edu/~horie/alphablend.html 54 | rgb apply_alpha(rgb pixel, rgb bg) { 55 | rgb result; 56 | result.as_rgba.a = 0xFF; 57 | u8 invalpha = 0xFF - pixel.as_rgba.a; 58 | 59 | result.as_rgba.r = (pixel.as_rgba.r * pixel.as_rgba.a + bg.as_rgba.r * invalpha)/256; 60 | result.as_rgba.g = (pixel.as_rgba.g * pixel.as_rgba.a + bg.as_rgba.g * invalpha)/256; 61 | result.as_rgba.b = (pixel.as_rgba.b * pixel.as_rgba.a + bg.as_rgba.b * invalpha)/256; 62 | 63 | return result; 64 | } 65 | -------------------------------------------------------------------------------- /time.c: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2008 Segher Boessenkool 6 | 7 | # This code is licensed to you under the terms of the GNU GPL, version 2; 8 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 9 | */ 10 | 11 | #include "hollywood.h" 12 | 13 | // Timebase frequency is bus frequency / 4. 14 | // following constants are from libogc - Wii only 15 | #define TB_BUS_CLOCK 243000000u 16 | #define TB_CORE_CLOCK 729000000u 17 | 18 | // constants that would be used for Gamecube 19 | //#define TB_BUS_CLOCK 162000000u 20 | //#define TB_CORE_CLOCK 486000000u 21 | 22 | #define TB_TIMER_CLOCK (TB_BUS_CLOCK/4000) //4th of the bus frequency 23 | 24 | #define ticks_to_microsecs(ticks) ((((u64)(ticks)*8)/(u64)(TB_TIMER_CLOCK/125))) 25 | #define microsecs_to_ticks(usec) (((u64)(usec)*(TB_TIMER_CLOCK/125))/8) 26 | #define secs_to_ticks(sec) ((u64)(sec)*(TB_TIMER_CLOCK*1000)) 27 | 28 | u64 mftb(void) 29 | { 30 | u32 hi, lo, dum; 31 | 32 | asm("0: mftbu %0 ; mftb %1 ; mftbu %2 ; cmplw %0,%2 ; bne 0b" 33 | : "=r"(hi), "=r"(lo), "=r"(dum)); 34 | return ((u64)hi << 32) | lo; 35 | } 36 | 37 | static void __delay(u64 ticks) 38 | { 39 | u64 start = mftb(); 40 | 41 | while (mftb() - start < ticks) 42 | ; 43 | } 44 | 45 | void usleep(u32 us) 46 | { 47 | __delay(microsecs_to_ticks(us)); 48 | } 49 | 50 | void sleep(u32 s) { 51 | __delay(secs_to_ticks(s)); 52 | } 53 | 54 | u64 mftb_usec(void) { 55 | return ticks_to_microsecs(mftb()); 56 | } 57 | -------------------------------------------------------------------------------- /gumboot.lst: -------------------------------------------------------------------------------- 1 | ## 2 | ## This is the default gumboot.lst menu for gumboot. 3 | ## 4 | 5 | # Video mode, possible settings: 6 | # NTSC, PAL50, PAL60, PROGRESSIVE 7 | video PAL60 8 | 9 | ## not yet supported - work in progress 10 | #splashimage (sd0,0)/gumboot/mario.png 11 | 12 | # supported colors are the official GRUB legacy set available at: 13 | # http://www.gnu.org/software/grub/manual/legacy/grub.html#color 14 | # syntax: 15 | #color NORMAL HIGHLIGHT HELPTEXT HEADING 16 | 17 | ## colors can also be expressed in RGB format 18 | #color rgb(255,0,0)/rgb(0,255,0) green/black white/blue 19 | 20 | ## official/default Gumboot color set 21 | color light-blue/white white/blue white/light-blue green/white 22 | 23 | ## timeout 0 means show the menu and do not enable any countdown 24 | timeout 30 25 | 26 | ## Gumboot-specific option 27 | ## do not display the menu and boot directly 28 | ## timeout must be zero 29 | ## alias of 'hiddenmenu' 30 | #nomenu 31 | 32 | default 0 33 | 34 | title wii-linux-ngx 35 | root (sd0,1)/linux 36 | kernel /zImage.ngx 37 | ## 'boot' is always implicit, but if specified must be the last line of a menu entry 38 | boot 39 | 40 | title Browse SD 41 | root (sd0,0) 42 | browse 43 | 44 | title Browse SD 2nd partition 45 | root (sd0,1) 46 | browse 47 | 48 | title Browse SD 3rd partition 49 | root (sd0,2) 50 | browse 51 | 52 | title Browse SD 4th partition 53 | root (sd0,3) 54 | browse 55 | 56 | title Bootmii GUI 57 | root (sd0,0) 58 | kernel /bootmii/gui.elf 59 | boot 60 | 61 | title Reboot 62 | reboot 63 | 64 | title Poweroff 65 | # 'halt' can also be used 66 | poweroff 67 | -------------------------------------------------------------------------------- /common.mk: -------------------------------------------------------------------------------- 1 | AR = $(PREFIX)ar 2 | AS = $(PREFIX)as 3 | CC = $(PREFIX)gcc 4 | CXX = $(PREFIX)g++ 5 | LD = $(PREFIX)ld 6 | OBJCOPY = $(PREFIX)objcopy 7 | RANLIB = $(PREFIX)ranlib 8 | STRIP = $(PREFIX)strip 9 | 10 | BIN2S = $(DEVKITPPC)/bin/bin2s 11 | 12 | ifeq ($(NOMAPFILE),) 13 | LDFLAGS += -Wl,-Map,$(TARGET).map 14 | endif 15 | 16 | ifneq ($(LDSCRIPT),) 17 | LDFLAGS += -Wl,-T$(LDSCRIPT) 18 | endif 19 | 20 | DEPDIR = .deps 21 | 22 | all: logo.c $(TARGET) 23 | 24 | $(TARGET): $(OBJS) 25 | @echo " LINK $@" 26 | @$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ 27 | $(STRIP) $@ 28 | 29 | ifneq ($(LDSCRIPT),) 30 | $(TARGET): $(LDSCRIPT) 31 | endif 32 | 33 | $(OBJDIR)/%.o: %.c 34 | @echo " COMPILE $<" 35 | @mkdir -p $(DEPDIR) 36 | @$(CC) $(CFLAGS) $(DEFINES) -Wp,-MMD,$(DEPDIR)/$(*F).d,-MQ,"$@",-MP -c $< -o $@ 37 | 38 | $(OBJDIR)/%.o: %.s 39 | @echo " ASSEMBLE $<" 40 | @$(CC) $(CFLAGS) $(DEFINES) $(ASFLAGS) -c $< -o $@ 41 | 42 | $(OBJDIR)/%.o: %.S 43 | @echo " ASSEMBLE $<" 44 | @$(CC) $(CFLAGS) $(DEFINES) $(ASFLAGS) -c $< -o $@ 45 | 46 | clean: 47 | rm -rf $(DEPDIR) 48 | rm -f $(TARGET) $(TARGET).map $(OBJS) 49 | 50 | define bin2o 51 | @echo " BIN2S $(notdir $<)" 52 | @$(BIN2S) -a 32 $< | $(AS) -o $(@) 53 | @echo "extern const u8" `(echo $( `(echo $(> `(echo $(> `(echo $( 6 | Copyright (C) 2009 John Kelley 7 | Copyright (C) 2009 bLAStY 8 | 9 | # This code is licensed to you under the terms of the GNU GPL, version 2; 10 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 11 | */ 12 | 13 | #ifndef __INPUT_H__ 14 | #define __INPUT_H__ 15 | 16 | #include "powerpc.h" 17 | 18 | #define PAD_BUTTON_LEFT 0x0001 19 | #define PAD_BUTTON_RIGHT 0x0002 20 | #define PAD_BUTTON_DOWN 0x0004 21 | #define PAD_BUTTON_UP 0x0008 22 | #define PAD_TRIGGER_Z 0x0010 23 | #define PAD_TRIGGER_R 0x0020 24 | #define PAD_TRIGGER_L 0x0040 25 | // unused 0x0080 26 | #define PAD_BUTTON_A 0x0100 27 | #define PAD_BUTTON_B 0x0200 28 | #define PAD_BUTTON_X 0x0400 29 | #define PAD_BUTTON_Y 0x0800 30 | #define PAD_BUTTON_START 0x1000 31 | #define PAD_ANY 0x1F7F 32 | 33 | #define GPIO_POWER PAD_BUTTON_DOWN 34 | #define GPIO_RESET PAD_BUTTON_UP 35 | #define GPIO_EJECT PAD_BUTTON_A 36 | 37 | // button long presses 38 | #define GPIO_RESET_LP PAD_BUTTON_A 39 | 40 | #define INPUT_WAIT_CYCLE_DELAY 20000 41 | 42 | typedef struct { 43 | u16 btns_held; 44 | u16 btns_up; 45 | u16 btns_down; 46 | s8 x, y, cx, cy; 47 | u8 l, r; 48 | } GC_Pad; 49 | 50 | void input_init(void); 51 | 52 | u16 pad_read(GC_Pad *pad, int chan); 53 | u16 gpio_read(void); 54 | 55 | u16 input_read(void); 56 | u16 input_wait(void); 57 | 58 | #endif 59 | 60 | -------------------------------------------------------------------------------- /old_diskio.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------- 2 | / Low level disk interface modlue include file R0.07 (C)ChaN, 2009 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO 6 | #define _DISKIO 7 | 8 | #define _READONLY 1 /* 1: Read-only mode */ 9 | 10 | #include "types.h" 11 | 12 | /* Status of Disk Functions */ 13 | typedef BYTE DSTATUS; 14 | 15 | /* Results of Disk Functions */ 16 | typedef enum { 17 | RES_OK = 0, /* 0: Successful */ 18 | RES_ERROR, /* 1: R/W Error */ 19 | RES_WRPRT, /* 2: Write Protected */ 20 | RES_NOTRDY, /* 3: Not Ready */ 21 | RES_PARERR /* 4: Invalid Parameter */ 22 | } DRESULT; 23 | 24 | /*---------------------------------------*/ 25 | /* Prototypes for disk control functions */ 26 | 27 | DSTATUS disk_initialize (BYTE); 28 | DSTATUS disk_status (BYTE); 29 | DRESULT disk_read (BYTE, BYTE*, DWORD, u32); 30 | #if _READONLY == 0 31 | DRESULT disk_write (BYTE, const BYTE*, DWORD, u32); 32 | #endif 33 | DRESULT disk_ioctl (BYTE, BYTE, void*); 34 | 35 | DWORD get_fattime(void); 36 | 37 | /* Disk Status Bits (DSTATUS) */ 38 | 39 | #define STA_NOINIT 0x01 /* Drive not initialized */ 40 | #define STA_NODISK 0x02 /* No medium in the drive */ 41 | #define STA_PROTECT 0x04 /* Write protected */ 42 | 43 | 44 | /* Command code for disk_ioctrl() */ 45 | 46 | /* Generic command */ 47 | #define CTRL_SYNC 0 /* Mandatory for write functions */ 48 | #define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */ 49 | #define GET_SECTOR_SIZE 2 50 | #define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */ 51 | 52 | #endif // _DISKIO 53 | -------------------------------------------------------------------------------- /exception.c: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2008 Segher Boessenkool 6 | 7 | # This code is licensed to you under the terms of the GNU GPL, version 2; 8 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 9 | */ 10 | 11 | #include "powerpc.h" 12 | #include "gecko.h" 13 | #include "string.h" 14 | 15 | extern char exception_2200_start, exception_2200_end; 16 | 17 | void exception_handler(int exception) 18 | { 19 | u32 *x; 20 | u32 i; 21 | 22 | gecko_printf("\nException %04x occurred!\n", exception); 23 | 24 | x = (u32 *)0x80002000; 25 | 26 | gecko_printf("\n R0..R7 R8..R15 R16..R23 R24..R31\n"); 27 | for (i = 0; i < 8; i++) { 28 | gecko_printf("%08x %08x %08x %08x\n", x[0], x[8], x[16], x[24]); 29 | x++; 30 | } 31 | x = (u32 *)0x80002080; 32 | 33 | gecko_printf("\n CR/XER LR/CTR SRR0/SRR1 DAR/DSISR\n"); 34 | for (i = 0; i < 2; i++) { 35 | gecko_printf("%08x %08x %08x %08x\n", x[0], x[2], x[4], x[6]); 36 | x++; 37 | } 38 | 39 | // Hang. 40 | for (;;) 41 | ; 42 | } 43 | 44 | void exception_init(void) 45 | { 46 | u32 vector; 47 | u32 len_2200; 48 | 49 | for (vector = 0x100; vector < 0x2000; vector += 0x10) { 50 | u32 *insn = (u32 *)(0x80000000 + vector); 51 | 52 | insn[0] = 0xbc002000; // stmw 0,0x2000(0) 53 | insn[1] = 0x38600000 | (u32)vector; // li 3,vector 54 | insn[2] = 0x48002202; // ba 0x2200 55 | insn[3] = 0; 56 | } 57 | sync_before_exec((void *)0x80000100, 0x1f00); 58 | 59 | len_2200 = &exception_2200_end - &exception_2200_start; 60 | memcpy((void *)0x80002200, &exception_2200_start, len_2200); 61 | sync_before_exec((void *)0x80002200, len_2200); 62 | } 63 | -------------------------------------------------------------------------------- /hollywood.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __HOLLYWOOD_H 3 | #define __HOLLYWOOD_H 4 | 5 | #include "types.h" 6 | 7 | // Hollywood stuff 8 | 9 | #define HW_REG_BASE 0xd800000 10 | #define HW_RESETS (HW_REG_BASE + 0x194) 11 | 12 | // PPC side of GPIO1 (Starlet can access this too) 13 | // Output state 14 | #define HW_GPIO1BOUT (HW_REG_BASE + 0x0c0) 15 | // Direction (1=output) 16 | #define HW_GPIO1BDIR (HW_REG_BASE + 0x0c4) 17 | // Input state 18 | #define HW_GPIO1BIN (HW_REG_BASE + 0x0c8) 19 | 20 | // hardware time/alarm 21 | #define HW_TIMER (HW_REG_BASE + 0x010) 22 | #define HW_ALARM (HW_REG_BASE + 0x014) 23 | 24 | #define HW_PPCIRQMASK (HW_REG_BASE + 0x034) 25 | #define HW_EXICTRL (HW_REG_BASE + 0x070) 26 | #define EXICTRL_ENABLE_EXI 1 27 | 28 | 29 | // Starlet side of GPIO1 30 | // Output state 31 | #define HW_GPIO1OUT (HW_REG_BASE + 0x0e0) 32 | // Direction (1=output) 33 | #define HW_GPIO1DIR (HW_REG_BASE + 0x0e4) 34 | 35 | #define HW_GPIO_SHUTDOWN (1<<1) 36 | 37 | // Basic I/O. 38 | 39 | static inline u32 read32(u32 addr) 40 | { 41 | u32 x; 42 | 43 | asm volatile("lwz %0,0(%1) ; sync" : "=r"(x) : "b"(0xc0000000 | addr)); 44 | 45 | return x; 46 | } 47 | 48 | static inline void write32(u32 addr, u32 x) 49 | { 50 | asm("stw %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr)); 51 | } 52 | 53 | static inline void mask32(u32 addr, u32 clear, u32 set) 54 | { 55 | write32(addr, (read32(addr)&(~clear)) | set); 56 | } 57 | 58 | static inline u16 read16(u32 addr) 59 | { 60 | u16 x; 61 | 62 | asm volatile("lhz %0,0(%1) ; sync" : "=r"(x) : "b"(0xc0000000 | addr)); 63 | 64 | return x; 65 | } 66 | 67 | static inline void write16(u32 addr, u16 x) 68 | { 69 | asm("sth %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr)); 70 | } 71 | 72 | #endif // __HOLLYWOOD_H 73 | -------------------------------------------------------------------------------- /console_common.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CONSOLE_COMMON_H 3 | #define __CONSOLE_COMMON_H 4 | 5 | #include "types.h" 6 | #include "config.h" 7 | #include "raster.h" 8 | 9 | #define CONSOLE_CHAR_WIDTH 8 10 | #define CONSOLE_CHAR_HEIGHT 16 11 | 12 | #define CONSOLE_ROW_HEIGHT CONSOLE_CHAR_HEIGHT 13 | 14 | #define RESOLUTION_W 640 15 | #define RESOLUTION_H 480 16 | 17 | #define CONSOLE_WIDTH RESOLUTION_W 18 | #define CONSOLE_X_OFFSET 0 19 | #ifdef GUMBOOT 20 | #define CONSOLE_Y_OFFSET (CONSOLE_CHAR_HEIGHT-2) 21 | #define CONSOLE_LINES ((RESOLUTION_H-CONSOLE_Y_OFFSET)/CONSOLE_ROW_HEIGHT - 1) 22 | #else 23 | #define CONSOLE_Y_OFFSET 0 24 | #define CONSOLE_LINES (RESOLUTION_H/CONSOLE_ROW_HEIGHT) 25 | #endif 26 | 27 | #define CONSOLE_COLUMNS (CONSOLE_WIDTH/CONSOLE_CHAR_WIDTH) 28 | 29 | #define FONT_NORMAL 0x0 30 | #define FONT_HELPTEXT 0x1 31 | #define FONT_HIGHLIGHT 0x2 32 | #define FONT_HEADING 0x3 33 | #define FONT_ERROR 0x4 34 | 35 | // utility function for software alpha blending 36 | rgb apply_alpha(rgb pixel, rgb bg); 37 | 38 | int gfx_printf_at(int x, int y, const char *fmt, ...); 39 | void gfx_print_at(int x, int y, const char *str); 40 | 41 | #define gfx_printch_at(x, y, c) gfx_draw_char(CONSOLE_X_OFFSET + (x) * CONSOLE_CHAR_WIDTH, CONSOLE_Y_OFFSET + (y) * CONSOLE_ROW_HEIGHT, c) 42 | 43 | extern char pf_buffer[4096]; 44 | 45 | // defined either by XFB or VFB implementations 46 | extern void gfx_draw_char(int x, int y, unsigned char c); 47 | extern int console_render_splash(raster rst); 48 | extern void console_blit(int dx, int dy, raster rst, rgb solid_bg, u32 *yuv_row); 49 | 50 | // defined in font.c 51 | extern unsigned char console_font_8x16[256*CONSOLE_CHAR_HEIGHT]; 52 | 53 | // some special characters in our console font 54 | #define DISP_UP 0x18 55 | #define DISP_DOWN 0x19 56 | #define DISP_RIGHT (DISP_DOWN+1) 57 | #define DISP_LEFT (DISP_DOWN+2) 58 | 59 | #endif // __CONSOLE_COMMON_H 60 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Gumboot 2 | 3 | Gumboot 4 | 5 | Gumboot is a configurable bootloader for Wii, aimed at running Linux with customizable kernel command line without the need of recompiling for every change. 6 | 7 | It is released in ELF format with the [wii-linux-ngx project](https://github.com/neagix/wii-linux-ngx): 8 | 9 | * [https://github.com/neagix/wii-linux-ngx/releases](https://github.com/neagix/wii-linux-ngx/releases) 10 | 11 | # Features 12 | 13 | * GRUB legacy colors, CSS-style rgb() triplets colors 14 | * navigate menu with power/reset buttons, activate with reset long press 15 | * GameCube gamepads support 16 | * timeout and default entry 17 | * customizable kernel command-line arguments 18 | * FAT16/FAT32 directory browsing and launching of ELF files 19 | * can read from all 4 primary partitions 20 | * reboot/poweroff 21 | * video mode selection 22 | * boot any ELF (including Bootmii) 23 | 24 | # Frequently Asked Questions 25 | 26 |
27 |
Does it support multiple partitions?
28 |
Yes, all primary partitions in FAT16 and FAT32 format are supported.
29 |
Does it support the GameCube controller?
30 |
Yes.
31 |
Does it support extended partitions?
32 |
No.
33 |
Does it support long filenames? exFAT?
34 |
No, the middleware has broken support for them. Make sure all your paths are in 8.3 format!
35 |
Does it support splash images?
36 |
No, it's a work in progress.
37 |
Does it support WiiMote?
38 |
No! It would require an USB and Bluetooth stack coded in, if you know what I am talking about.
39 |
Does it support USB storage?
40 |
No, see above.
41 |
42 | 43 | # Screenshot 44 | 45 | This is a screenshot of the default [gumboot.lst](https://github.com/neagix/wii-linux-ngx/blob/master/gumboot.lst) menu: 46 | 47 | Gumboot default menu 48 | 49 | # Thanks 50 | 51 | Thanks to the following people: 52 | * marcan 53 | -------------------------------------------------------------------------------- /powerpc.h: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2008 Segher Boessenkool 6 | 7 | # This code is licensed to you under the terms of the GNU GPL, version 2; 8 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 9 | */ 10 | 11 | #ifndef __PPC_H__ 12 | #define __PPC_H__ 13 | 14 | #include "time.h" 15 | #include "hollywood.h" 16 | 17 | void dsp_reset(void); 18 | 19 | void powerpc_hang(void); 20 | void powerpc_reset(void); 21 | void powerpc_poweroff(void); 22 | 23 | #include "types.h" 24 | #include "printf.h" 25 | 26 | #define OK 0 27 | #define EFAIL 1 28 | 29 | #define MEM2_BSS __attribute__ ((section (".bss.mem2"))) 30 | #define MEM2_DATA __attribute__ ((section (".data.mem2"))) 31 | #define MEM2_RODATA __attribute__ ((section (".rodata.mem2"))) 32 | #define ALIGNED(x) __attribute__((aligned(x))) 33 | 34 | #define STACK_ALIGN(type, name, cnt, alignment) \ 35 | u8 _al__##name[((sizeof(type)*(cnt)) + (alignment) + \ 36 | (((sizeof(type)*(cnt))%(alignment)) > 0 ? ((alignment) - \ 37 | ((sizeof(type)*(cnt))%(alignment))) : 0))]; \ 38 | type *name = (type*)(((u32)(_al__##name)) + ((alignment) - (( \ 39 | (u32)(_al__##name))&((alignment)-1)))) 40 | 41 | 42 | // Address mapping. 43 | 44 | static inline u32 virt_to_phys(const void *p) 45 | { 46 | return (u32)p & 0x7fffffff; 47 | } 48 | 49 | static inline void *phys_to_virt(u32 x) 50 | { 51 | return (void *)(x | 0x80000000); 52 | } 53 | 54 | 55 | // Cache synchronisation. 56 | 57 | void sync_before_read(void *p, u32 len); 58 | void sync_after_write(const void *p, u32 len); 59 | void sync_before_exec(const void *p, u32 len); 60 | 61 | 62 | // Special purpose registers. 63 | 64 | #define mtspr(n, x) do { asm("mtspr %1,%0" : : "r"(x), "i"(n)); } while (0) 65 | #define mfspr(n) ({ \ 66 | u32 x; asm volatile("mfspr %0,%1" : "=r"(x) : "i"(n)); x; \ 67 | }) 68 | 69 | 70 | // Exceptions. 71 | 72 | void exception_init(void); 73 | 74 | 75 | // Debug: blink the tray led. 76 | 77 | static inline void blink(void) 78 | { 79 | write32(0x0d8000c0, read32(0x0d8000c0) ^ 0x20); 80 | } 81 | 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /lstrender/virtual_console.c: -------------------------------------------------------------------------------- 1 | 2 | #include "virtual_console.h" 3 | #include "../console_common.h" 4 | 5 | #include 6 | #include 7 | 8 | unsigned char *vfb; 9 | unsigned vfb_stride; 10 | 11 | int selected_font; 12 | 13 | void select_font(int font) { 14 | selected_font = font; 15 | } 16 | 17 | static void memset32(u32 *dst, u32 setval, u32 count) { 18 | while(count--) { 19 | *dst = setval; 20 | 21 | dst++; 22 | } 23 | } 24 | 25 | void gfx_clear(int offset_x, int offset_y, int w, int h, rgb c) { 26 | u32 *fb = (u32 *)vfb; 27 | 28 | fb += (offset_y * CONSOLE_CHAR_HEIGHT) * (vfb_stride/4); 29 | fb += offset_x * CONSOLE_CHAR_WIDTH; 30 | 31 | for(int y = 0; y < h*CONSOLE_CHAR_HEIGHT; y++) { 32 | memset32(fb, c.as_u32, w * CONSOLE_CHAR_WIDTH); 33 | 34 | fb += vfb_stride/4; 35 | } 36 | } 37 | 38 | static void memcpy_font(u32 *dst, unsigned char font_row, rgb *fg, rgb *bg) { 39 | for (u8 x = 0; x < CONSOLE_CHAR_WIDTH; x++) { 40 | if ((font_row >> (CONSOLE_CHAR_WIDTH-1-x)) & 0x01) { 41 | dst[x] = fg->as_u32; 42 | } else { 43 | dst[x] = bg->as_u32; 44 | } 45 | } 46 | } 47 | 48 | void gfx_draw_char(int dx, int dy, unsigned char c) { 49 | u32 *fb = (u32 *)vfb; 50 | rgb *fg, *bg; 51 | 52 | switch (selected_font) { 53 | case FONT_HEADING: 54 | fg = &config_color_heading[0]; 55 | bg = &config_color_heading[1]; 56 | break; 57 | case FONT_NORMAL: 58 | fg = &config_color_normal[0]; 59 | bg = &config_color_normal[1]; 60 | break; 61 | case FONT_HELPTEXT: 62 | fg = &config_color_helptext[0]; 63 | bg = &config_color_helptext[1]; 64 | break; 65 | case FONT_HIGHLIGHT: 66 | fg = &config_color_highlight[0]; 67 | bg = &config_color_highlight[1]; 68 | break; 69 | case FONT_ERROR: 70 | fg = &color_error[0]; 71 | bg = &color_error[1]; 72 | break; 73 | default: 74 | // PANIC! 75 | return; 76 | } 77 | 78 | fb += dy * vfb_stride/4; 79 | fb += dx; 80 | 81 | for(u8 y = 0; y < CONSOLE_CHAR_HEIGHT; y++) { 82 | unsigned char font_row = console_font_8x16[c*CONSOLE_CHAR_HEIGHT + y]; 83 | memcpy_font(fb, font_row, fg, bg); 84 | 85 | fb += vfb_stride/4; 86 | } 87 | } 88 | 89 | void console_blit(int dx, int dy, raster rst, rgb solid_bg, u32 *unused_yuv_row) { 90 | u32 x, y; 91 | u32 *fb = (u32 *)vfb; 92 | u32 *pixel_data = (u32 *)rst.pixels; 93 | 94 | fb += dy * vfb_stride/4; 95 | fb += dx; 96 | 97 | for(y = 0; y < rst.height; y++) { 98 | for(x = 0;x < rst.width; x++) { 99 | rgb pixel = {.as_u32 = pixel_data[x + y * rst.width]}; 100 | pixel = apply_alpha(pixel, solid_bg); 101 | 102 | fb[x] = pixel.as_u32; 103 | } 104 | 105 | fb += vfb_stride/4; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /video_low.h: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | low-level video support for the BootMii UI 4 | 5 | Copyright (C) 2008, 2009 Hector Martin "marcan" 6 | Copyright (C) 2009 Haxx Enterprises 7 | Copyright (C) 2009 Sven Peter 8 | # This code is licensed to you under the terms of the GNU GPL, version 2; 9 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 10 | 11 | Some routines and initialization constants originally came from the 12 | "GAMECUBE LOW LEVEL INFO" document and sourcecode released by Titanik 13 | of Crazy Nation and the GC Linux project. 14 | */ 15 | 16 | #ifndef VIDEO_LOW_H 17 | #define VIDEO_LOW_H 18 | 19 | #define MEM_VIDEO_BASE (0xCC002000) ///< Memory address of Video Interface 20 | #define MEM_VIDEO_BASE_PTR (u32*)MEM_VIDEO_BASE ///< Pointer to Video Interface 21 | 22 | // 32-bit-wide registers 23 | #define R_VIDEO_VTIMING (MEM_VIDEO_BASE+0x00) ///< Vertical timing. 24 | #define R_VIDEO_STATUS1 (MEM_VIDEO_BASE+0x02) ///< Status? register location. 25 | #define R_VIDEO_PSB_ODD (MEM_VIDEO_BASE+0x00) ///< Postblank odd. 26 | #define R_VIDEO_PRB_ODD (MEM_VIDEO_BASE+0x00) ///< Preblank odd. 27 | #define R_VIDEO_PSB_EVEN (MEM_VIDEO_BASE+0x00) ///< Postblank even. 28 | #define R_VIDEO_PRB_EVEN (MEM_VIDEO_BASE+0x00) ///< Preblank even. 29 | #define R_VIDEO_FRAMEBUFFER_1 (MEM_VIDEO_BASE+0x1C) ///< Framebuffer1 register location. 30 | #define R_VIDEO_FRAMEBUFFER_2 (MEM_VIDEO_BASE+0x24) ///< Framebuffer2 register location. 31 | // 16-bit-wide registers 32 | #define R_VIDEO_HALFLINE_1 (MEM_VIDEO_BASE+0x2C) ///< HalfLine1 register location. 33 | #define R_VIDEO_HALFLINE_2 (MEM_VIDEO_BASE+0x2E) ///< HalfLine2 register location. 34 | #define R_VIDEO_STATUS (MEM_VIDEO_BASE+0x6C) ///< VideoStatus register location. 35 | #define R_VIDEO_VISEL (MEM_VIDEO_BASE+0x6E) // cable detect 36 | 37 | // Constants for VIDEO_Init() 38 | #define VIDEO_640X480_NTSCi_YUV16 (0) 39 | #define VIDEO_640X480_PAL50_YUV16 (1) 40 | #define VIDEO_640X480_PAL60_YUV16 (2) 41 | #define VIDEO_640X480_NTSCp_YUV16 (3) 42 | 43 | // Constants for VIDEO_SetFrameBuffer 44 | #define VIDEO_FRAMEBUFFER_1 (1) 45 | #define VIDEO_FRAMEBUFFER_2 (2) 46 | #define VIDEO_FRAMEBUFFER_BOTH (0) 47 | 48 | void VIDEO_Init (int VideoMode); 49 | void VIDEO_SetFrameBuffer (void *FrameBufferAddr); 50 | void VIDEO_WaitVSync (void); 51 | void VIDEO_BlackOut (void); 52 | void VIDEO_Shutdown (void); 53 | void VISetupEncoder (void); 54 | 55 | #endif /* VIDEO_H */ 56 | 57 | -------------------------------------------------------------------------------- /fatfs/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface module include file (C)ChaN, 2014 / 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO_DEFINED 6 | #define _DISKIO_DEFINED 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #include "integer.h" 13 | 14 | 15 | /* Status of Disk Functions */ 16 | typedef BYTE DSTATUS; 17 | 18 | /* Results of Disk Functions */ 19 | typedef enum { 20 | RES_OK = 0, /* 0: Successful */ 21 | RES_ERROR, /* 1: R/W Error */ 22 | RES_WRPRT, /* 2: Write Protected */ 23 | RES_NOTRDY, /* 3: Not Ready */ 24 | RES_PARERR /* 4: Invalid Parameter */ 25 | } DRESULT; 26 | 27 | 28 | /*---------------------------------------*/ 29 | /* Prototypes for disk control functions */ 30 | 31 | 32 | DSTATUS disk_initialize (BYTE pdrv); 33 | DSTATUS disk_status (BYTE pdrv); 34 | DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); 35 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); 36 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 37 | 38 | 39 | /* Disk Status Bits (DSTATUS) */ 40 | 41 | #define STA_NOINIT 0x01 /* Drive not initialized */ 42 | #define STA_NODISK 0x02 /* No medium in the drive */ 43 | #define STA_PROTECT 0x04 /* Write protected */ 44 | 45 | 46 | /* Command code for disk_ioctrl fucntion */ 47 | 48 | /* Generic command (Used by FatFs) */ 49 | #define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ 50 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ 51 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ 52 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ 53 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ 54 | 55 | /* Generic command (Not used by FatFs) */ 56 | #define CTRL_POWER 5 /* Get/Set power status */ 57 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 58 | #define CTRL_EJECT 7 /* Eject media */ 59 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 60 | 61 | /* MMC/SDC specific ioctl command */ 62 | #define MMC_GET_TYPE 10 /* Get card type */ 63 | #define MMC_GET_CSD 11 /* Get CSD */ 64 | #define MMC_GET_CID 12 /* Get CID */ 65 | #define MMC_GET_OCR 13 /* Get OCR */ 66 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 67 | #define ISDIO_READ 55 /* Read data form SD iSDIO register */ 68 | #define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ 69 | #define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ 70 | 71 | /* ATA/CF specific ioctl command */ 72 | #define ATA_GET_REV 20 /* Get F/W revision */ 73 | #define ATA_GET_MODEL 21 /* Get model name */ 74 | #define ATA_GET_SN 22 /* Get serial number */ 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /menu.c: -------------------------------------------------------------------------------- 1 | 2 | #include "menu.h" 3 | #include "string.h" 4 | #include "powerpc.h" 5 | #include "powerpc_elf.h" 6 | #include "log.h" 7 | #include "time.h" 8 | #include "fatfs/ff.h" 9 | #include "menu_render.h" 10 | #include "console_common.h" 11 | #include "video_low.h" 12 | #include "malloc.h" 13 | #include "browse.h" 14 | 15 | void menu_down(void) { 16 | int max; 17 | if (browse_menu_entries_count) { 18 | max = browse_menu_entries_count; 19 | } else { 20 | max = config_entries_count; 21 | } 22 | menu_selection++; 23 | if (menu_selection == max) 24 | menu_selection = 0; 25 | menu_draw_entries_and_help(); 26 | } 27 | 28 | void menu_up(void) { 29 | int max; 30 | if (browse_menu_entries_count) { 31 | max = browse_menu_entries_count; 32 | } else { 33 | max = config_entries_count; 34 | } 35 | if (menu_selection == 0) 36 | menu_selection = max-1; 37 | else 38 | menu_selection--; 39 | menu_draw_entries_and_help(); 40 | } 41 | 42 | int menu_activate(void) { 43 | int m_err; 44 | if (browse_menu_entries_count) { 45 | return menu_browse_activate(); 46 | } 47 | stanza *sel = &config_entries[menu_selection]; 48 | 49 | if (sel->reboot) { 50 | VIDEO_Shutdown(); 51 | powerpc_reset(); 52 | return 0; 53 | } 54 | if (sel->poweroff) { 55 | VIDEO_Shutdown(); 56 | powerpc_poweroff(); 57 | return 0; 58 | } 59 | 60 | // if root is set, initialize the corresponding volume 61 | FATFS fatfs; 62 | char target[3]; 63 | if (sel->root) { 64 | memcpy(target, sel->root, 3); 65 | target[2] = 0; 66 | 67 | FRESULT res = f_mount(&fatfs, target, 1); 68 | if (res != FR_OK) { 69 | log_printf("could not mount %s: %d\n", target, res); 70 | return res; 71 | } 72 | } 73 | 74 | //NOTE: fatfs is not unmounted when browsing, re-mounting will cleanup the previous object 75 | if (sel->browse) { 76 | old_menu_selection = menu_selection; 77 | 78 | // directory browse, uses 'root' to set starting partition and directory 79 | // otherwise starts from first partition and root directory 80 | if (sel->root) { 81 | memcpy(browse_current_path, sel->root, strlen(sel->root)+1); 82 | } else { 83 | // use first logical drive by default 84 | browse_current_path[0] = '0'; 85 | browse_current_path[1] = ':'; 86 | browse_current_path[2] = 0; 87 | } 88 | 89 | return menu_browse(); 90 | } 91 | 92 | int err; 93 | if (!sel->kernel) { 94 | log_printf("BUG: invalid menu entry\n"); 95 | err = -1; 96 | goto unmount_and_exit; 97 | } 98 | 99 | // at this point root must have been setup 100 | // and we are going to boot a kernel 101 | 102 | // root has never trailing slash, kernel has always leading slash 103 | char *kernel_fn = strcat(sel->root, sel->kernel); 104 | err = try_boot_file(kernel_fn, sel->kernel_args); 105 | free(kernel_fn); 106 | 107 | unmount_and_exit: 108 | m_err = f_mount(NULL, target, 0); 109 | if (m_err) { 110 | log_printf("failed to unmount: %d\n", m_err); 111 | } 112 | 113 | return err; 114 | } 115 | -------------------------------------------------------------------------------- /old_diskio.c: -------------------------------------------------------------------------------- 1 | /* 2 | diskio.c -- glue interface to ElmChan FAT FS driver. Part of the 3 | BootMii project. 4 | 5 | Copyright (C) 2008, 2009 Haxx Enterprises 6 | Copyright (C) 2008, 2009 Sven Peter 7 | 8 | # This code is licensed to you under the terms of the GNU GPL, version 2; 9 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 10 | */ 11 | 12 | #include "powerpc.h" 13 | #include "ipc.h" 14 | #include "mini_ipc.h" 15 | #include "diskio.h" 16 | #include "string.h" 17 | 18 | static u8 *buffer[512] __attribute__((aligned(32))); 19 | 20 | DSTATUS disk_status (BYTE drv) 21 | { 22 | (void) drv; 23 | 24 | int state = sd_get_state(); 25 | 26 | switch (state) { 27 | case SDMMC_NO_CARD: 28 | return STA_NODISK; 29 | 30 | case SDMMC_NEW_CARD: 31 | return STA_NOINIT; 32 | 33 | default: 34 | return 0; 35 | } 36 | } 37 | 38 | DSTATUS disk_initialize (BYTE drv) 39 | { 40 | (void) drv; 41 | 42 | int state = sd_get_state(); 43 | 44 | switch (state) { 45 | case SDMMC_NO_CARD: 46 | return STA_NODISK; 47 | 48 | case SDMMC_NEW_CARD: 49 | if (sd_mount()) 50 | return STA_NOINIT; 51 | else 52 | return 0; 53 | 54 | default: 55 | return 0; 56 | } 57 | } 58 | 59 | 60 | DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, u32 count) 61 | { 62 | u32 i; 63 | DRESULT res; 64 | (void) drv; 65 | 66 | if (count > 1 && ((u32) buff % 64) == 0) { 67 | if (sd_read(sector, count, buff) != 0) 68 | return RES_ERROR; 69 | return RES_OK; 70 | } 71 | 72 | res = RES_OK; 73 | for (i = 0; i < count; i++) { 74 | if (sd_read(sector + i, 1, buffer) != 0) { 75 | res = RES_ERROR; 76 | break; 77 | } 78 | 79 | memcpy(buff + i * 512, buffer, 512); 80 | } 81 | 82 | return res; 83 | } 84 | 85 | #if _READONLY == 0 86 | DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, u32 count) 87 | { 88 | u32 i; 89 | DRESULT res; 90 | (void) drv; 91 | 92 | res = RES_OK; 93 | if (count > 1 && ((u32) buff % 64) == 0) { 94 | if (sd_write(sector, count, buff) != 0) 95 | return RES_ERROR; 96 | return RES_OK; 97 | } 98 | 99 | for (i = 0; i < count; i++) { 100 | memcpy(buffer, buff + i * 512, 512); 101 | if (sd_write(sector + i, 1, buffer) != 0) { 102 | res = RES_ERROR; 103 | break; 104 | } 105 | } 106 | 107 | return res; 108 | } 109 | #endif /* _READONLY */ 110 | 111 | DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff) 112 | { 113 | (void) drv; 114 | u32 *buff_u32 = (u32 *) buff; 115 | DRESULT res = RES_OK; 116 | 117 | switch (ctrl) { 118 | case CTRL_SYNC: 119 | break; 120 | case GET_SECTOR_COUNT: 121 | *buff_u32 = sd_getsize(); 122 | break; 123 | case GET_SECTOR_SIZE: 124 | *buff_u32 = 512; 125 | break; 126 | case GET_BLOCK_SIZE: 127 | *buff_u32 = 512; 128 | break; 129 | default: 130 | res = RES_PARERR; 131 | break; 132 | } 133 | 134 | return res; 135 | } 136 | 137 | DWORD get_fattime(void) 138 | { 139 | return 0; // TODO 140 | } 141 | -------------------------------------------------------------------------------- /lstrender/lstrender.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "lodepng.h" 6 | 7 | #include "../config.h" 8 | #include "../menu_render.h" 9 | #include "../raster.h" 10 | 11 | #define font_test 0 12 | 13 | /* The image argument has width * height RGBA pixels or width * height * 4 bytes */ 14 | void encodeOneStep(const char* filename, const unsigned char* image, unsigned width, unsigned height) 15 | { 16 | /*Encode the image*/ 17 | unsigned error = lodepng_encode32_file(filename, image, width, height); 18 | 19 | /*if there's an error, display it*/ 20 | if(error) printf("error %u: %s\n", error, lodepng_error_text(error)); 21 | } 22 | 23 | int main(int argc, char **argv) 24 | { 25 | // sanity check 26 | if (sizeof(rgb) != 4) { 27 | fprintf(stderr, "BUG: rgba is not 4 bytes\n"); 28 | return -1; 29 | } 30 | 31 | if (argc != 3) { 32 | fprintf(stderr, "Usage: lstrender gumboot.lst preview.png\n"); 33 | return -1; 34 | } 35 | 36 | // load configuration file into memory 37 | 38 | FILE *f = fopen(argv[1], "rb"); 39 | if (!f) { 40 | fprintf(stderr, "ERROR: could not open '%s'\n", argv[1]); 41 | return -2; 42 | } 43 | fseek(f, 0, SEEK_END); 44 | long fsize = ftell(f); 45 | fseek(f, 0, SEEK_SET); //same as rewind(f); 46 | 47 | char *config_data = malloc(fsize + 1); 48 | fread(config_data, fsize, 1, f); 49 | fclose(f); 50 | 51 | config_data[fsize] = 0; 52 | 53 | int err = config_load_from_buffer(config_data, fsize); 54 | free(config_data); 55 | if (err) { 56 | fprintf(stderr, "ERROR: %d\n", err); 57 | return -1; 58 | } 59 | 60 | for(int i =0;i 6 | 7 | # This code is licensed to you under the terms of the GNU GPL, version 2; 8 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 9 | */ 10 | 11 | #define IBAT0U 528 12 | #define IBAT0L 529 13 | #define IBAT1U 530 14 | #define IBAT1L 531 15 | #define IBAT2U 532 16 | #define IBAT2L 533 17 | #define IBAT3U 534 18 | #define IBAT3L 535 19 | #define IBAT4U 560 20 | #define IBAT4L 561 21 | #define IBAT5U 562 22 | #define IBAT5L 563 23 | #define IBAT6U 564 24 | #define IBAT6L 565 25 | #define IBAT7U 566 26 | #define IBAT7L 567 27 | 28 | #define DBAT0U 536 29 | #define DBAT0L 537 30 | #define DBAT1U 538 31 | #define DBAT1L 539 32 | #define DBAT2U 540 33 | #define DBAT2L 541 34 | #define DBAT3U 542 35 | #define DBAT3L 543 36 | #define DBAT4U 568 37 | #define DBAT4L 569 38 | #define DBAT5U 570 39 | #define DBAT5L 571 40 | #define DBAT6U 572 41 | #define DBAT6L 573 42 | #define DBAT7U 574 43 | #define DBAT7L 575 44 | 45 | 46 | .text 47 | .section .realmode,"ax",@progbits 48 | .extern _start 49 | .align 2 50 | .globl _realmode_vector 51 | 52 | _realmode_vector: 53 | // HID0 = 00110c64: 54 | // bus checkstops off, sleep modes off, 55 | // caches off, caches invalidate, 56 | // store gathering off, enable data cache 57 | // flush assist, enable branch target cache, 58 | // enable branch history table 59 | lis 3,0x0011 ; ori 3,3,0x0c64 ; mtspr 1008,3 ; isync 60 | 61 | // MSR = 00002000 (FP on) 62 | li 4,0x2000 ; mtmsr 4 63 | 64 | // HID0 |= 0000c000 (caches on) 65 | ori 3,3,0xc000 ; mtspr 1008,3 ; isync 66 | 67 | // clear all BATs 68 | li 0,0 69 | mtspr 528,0 ; mtspr 530,0 ; mtspr 532,0 ; mtspr 534,0 // IBATU 0..3 70 | mtspr 536,0 ; mtspr 538,0 ; mtspr 540,0 ; mtspr 542,0 // DBATU 0..3 71 | mtspr 560,0 ; mtspr 562,0 ; mtspr 564,0 ; mtspr 566,0 // IBATU 4..7 72 | mtspr 568,0 ; mtspr 570,0 ; mtspr 572,0 ; mtspr 574,0 // DBATU 4..7 73 | isync 74 | 75 | // clear all SRs 76 | lis 0,0x8000 77 | mtsr 0,0 ; mtsr 1,0 ; mtsr 2,0 ; mtsr 3,0 78 | mtsr 4,0 ; mtsr 5,0 ; mtsr 6,0 ; mtsr 7,0 79 | mtsr 8,0 ; mtsr 9,0 ; mtsr 10,0 ; mtsr 11,0 80 | mtsr 12,0 ; mtsr 13,0 ; mtsr 14,0 ; mtsr 15,0 81 | isync 82 | 83 | // set [DI]BAT0 for 256MB@80000000, 84 | // real 00000000, WIMG=0000, R/W 85 | li 3,2 ; lis 4,0x8000 ; ori 4,4,0x1fff 86 | mtspr IBAT0L,3 ; mtspr IBAT0U,4 ; mtspr DBAT0L,3 ; mtspr DBAT0U,4 ; isync 87 | 88 | // set [DI]BAT4 for 256MB@90000000, 89 | // real 10000000, WIMG=0000, R/W 90 | addis 3,3,0x1000 ; addis 4,4,0x1000 91 | mtspr IBAT4L,3 ; mtspr IBAT4U,4 ; mtspr DBAT4L,3 ; mtspr DBAT4U,4 ; isync 92 | 93 | // set DBAT1 for 256MB@c0000000, 94 | // real 00000000, WIMG=0101, R/W 95 | li 3,0x2a ; lis 4,0xc000 ; ori 4,4,0x1fff 96 | mtspr DBAT1L,3 ; mtspr DBAT1U,4 ; isync 97 | 98 | // set DBAT5 for 256MB@d0000000, 99 | // real 10000000, WIMG=0101, R/W 100 | addis 3,3,0x1000 ; addis 4,4,0x1000 101 | mtspr DBAT5L,3 ; mtspr DBAT5U,4 ; isync 102 | 103 | // enable [DI]BAT4-7 in HID4 104 | lis 3, 0x8200 105 | mtspr 1011,3 106 | 107 | // set MSR[DR:IR] = 11, jump to _start 108 | lis 3,_start@h ; ori 3,3,_start@l ; mtsrr0 3 109 | 110 | mfmsr 3 ; ori 3,3,0x30 ; mtsrr1 3 111 | rfi 112 | 113 | -------------------------------------------------------------------------------- /string.c: -------------------------------------------------------------------------------- 1 | /* string.c -- standard C string-manipulation functions. 2 | 3 | Copyright (C) 2008 Segher Boessenkool 4 | Copyright (C) 2009 Haxx Enterprises 5 | 6 | Portions taken from the Public Domain C Library (PDCLib). 7 | https://negix.net/trac/pdclib 8 | 9 | # This code is licensed to you under the terms of the GNU GPL, version 2; 10 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 11 | */ 12 | 13 | #include "string.h" 14 | #include "malloc.h" 15 | 16 | size_t strlen(const char *s) 17 | { 18 | size_t len; 19 | 20 | for (len = 0; s[len]; len++) 21 | ; 22 | 23 | return len; 24 | } 25 | 26 | size_t strnlen(const char *s, size_t count) 27 | { 28 | size_t len; 29 | 30 | for (len = 0; s[len] && len < count; len++) 31 | ; 32 | 33 | return len; 34 | } 35 | 36 | char *strdup(const char *s) { 37 | size_t l = strlen(s)+1; 38 | char *r = malloc(l); 39 | memcpy(r, s, l); 40 | return r; 41 | } 42 | 43 | void *memset(void *b, int c, size_t len) 44 | { 45 | size_t i; 46 | 47 | for (i = 0; i < len; i++) 48 | ((unsigned char *)b)[i] = c; 49 | 50 | return b; 51 | } 52 | 53 | void *memcpy(void *dst, const void *src, size_t len) 54 | { 55 | size_t i; 56 | 57 | for (i = 0; i < len; i++) 58 | ((unsigned char *)dst)[i] = ((unsigned char *)src)[i]; 59 | 60 | return dst; 61 | } 62 | 63 | int memcmp(const void *s1, const void *s2, size_t len) 64 | { 65 | size_t i; 66 | const unsigned char * p1 = (const unsigned char *) s1; 67 | const unsigned char * p2 = (const unsigned char *) s2; 68 | 69 | for (i = 0; i < len; i++) 70 | if (p1[i] != p2[i]) return p1[i] - p2[i]; 71 | 72 | return 0; 73 | } 74 | 75 | int strcmp(const char *s1, const char *s2) 76 | { 77 | size_t i; 78 | 79 | for (i = 0; s1[i] && s1[i] == s2[i]; i++) 80 | ; 81 | 82 | return s1[i] - s2[i]; 83 | } 84 | 85 | int strncmp(const char *s1, const char *s2, size_t n) 86 | { 87 | size_t i; 88 | 89 | for (i = 0; i < n && s1[i] && s1[i] == s2[i]; i++) 90 | ; 91 | if (i == n) return 0; 92 | return s1[i] - s2[i]; 93 | } 94 | 95 | size_t strlcpy(char *dest, const char *src, size_t maxlen) 96 | { 97 | size_t len,needed; 98 | 99 | len = needed = strnlen(src, maxlen-1) + 1; 100 | if (len >= maxlen) 101 | len = maxlen-1; 102 | 103 | memcpy(dest, src, len); 104 | dest[len]='\0'; 105 | 106 | return needed-1; 107 | } 108 | 109 | char *strcat(const char *dest, const char *src) { 110 | int l1 = strlen(dest), 111 | l2 = strlen(src); 112 | char *result = malloc(l1+l2+1); 113 | memcpy(result, dest, l1); 114 | memcpy(result+l1, src, l2+1); 115 | return result; 116 | } 117 | 118 | size_t strlcat(char *dest, const char *src, size_t maxlen) 119 | { 120 | size_t used; 121 | 122 | used = strnlen(dest, maxlen-1); 123 | return used + strlcpy(dest + used, src, maxlen - used); 124 | } 125 | 126 | char * strchr(const char *s, char c) 127 | { 128 | size_t i; 129 | 130 | for (i = 0; s[i]; i++) 131 | if (s[i] == c) return (char *)s + i; 132 | 133 | return NULL; 134 | } 135 | 136 | size_t strspn(const char *s1, const char *s2) 137 | { 138 | size_t len = 0; 139 | const char *p; 140 | 141 | while (s1[len]) { 142 | p = s2; 143 | while (*p) { 144 | if (s1[len] == *p) 145 | break; 146 | 147 | ++p; 148 | } 149 | if (!*p) 150 | return len; 151 | 152 | ++len; 153 | } 154 | 155 | return len; 156 | } 157 | 158 | size_t strcspn(const char *s1, const char *s2) 159 | { 160 | size_t len = 0; 161 | const char *p; 162 | 163 | while (s1[len]) { 164 | p = s2; 165 | while (*p) 166 | if (s1[len] == *p++) 167 | return len; 168 | 169 | ++len; 170 | } 171 | 172 | return len; 173 | } 174 | 175 | -------------------------------------------------------------------------------- /mini_ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | mini_ipc.h -- public PowerPC-side interface to mini. Part of the 3 | BootMii project. 4 | 5 | Copyright (C) 2009 Andre Heider "dhewg" 6 | Copyright (C) 2009 Haxx Enterprises 7 | Copyright (C) 2009 John Kelley 8 | Copyright (C) 2008, 2009 Sven Peter 9 | 10 | # This code is licensed to you under the terms of the GNU GPL, version 2; 11 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 12 | */ 13 | 14 | #ifndef __MINI_IPC_H__ 15 | #define __MINI_IPC_H__ 16 | 17 | #include "types.h" 18 | 19 | #define SDHC_ENOCARD -0x1001 20 | #define SDHC_ESTRANGE -0x1002 21 | #define SDHC_EOVERFLOW -0x1003 22 | #define SDHC_ETIMEDOUT -0x1004 23 | #define SDHC_EINVAL -0x1005 24 | #define SDHC_EIO -0x1006 25 | 26 | #define SDMMC_NO_CARD 1 27 | #define SDMMC_NEW_CARD 2 28 | #define SDMMC_INSERTED 3 29 | 30 | #define NAND_ECC_OK 0 31 | #define NAND_ECC_CORRECTED 1 32 | #define NAND_ECC_UNCORRECTABLE -1 33 | 34 | int sd_get_state(void); 35 | int sd_protected(void); 36 | int sd_mount(void); 37 | int sd_select(void); 38 | int sd_read(u32 start_block, u32 blk_cnt, void *buffer); 39 | int sd_write(u32 start_block, u32 blk_cnt, const void *buffer); 40 | u32 sd_getsize(void); 41 | 42 | int ipc_powerpc_boot(const void *addr, u32 len); 43 | 44 | #define TMD_BM_MARK(x) ((u16*)&(x->reserved[4])) 45 | // 'BM' 46 | #define TMD_BM_MAGIC 0x424d 47 | 48 | typedef struct { 49 | u32 type; 50 | u8 sig[256]; 51 | u8 fill[60]; 52 | } __attribute__((packed)) sig_rsa2048; 53 | 54 | typedef struct { 55 | u32 cid; 56 | u16 index; 57 | u16 type; 58 | u64 size; 59 | u8 hash[20]; 60 | } __attribute__((packed)) tmd_content; 61 | 62 | typedef struct { 63 | sig_rsa2048 signature; 64 | char issuer[0x40]; 65 | u8 version; 66 | u8 ca_crl_version; 67 | u8 signer_crl_version; 68 | u8 fill2; 69 | u64 sys_version; 70 | u64 title_id; 71 | u32 title_type; 72 | u16 group_id; 73 | u16 zero; 74 | u16 region; 75 | u8 ratings[16]; 76 | u8 reserved[42]; 77 | u32 access_rights; 78 | u16 title_version; 79 | u16 num_contents; 80 | u16 boot_index; 81 | u16 fill3; 82 | tmd_content boot_content; 83 | } __attribute__((packed)) tmd; 84 | 85 | u32 boot2_run(u32 hi, u32 lo); 86 | tmd *boot2_tmd(void); 87 | 88 | typedef struct 89 | { 90 | u8 boot1_hash[20]; 91 | u8 common_key[16]; 92 | u32 ng_id; 93 | union { // first two bytes of nand_hmac overlap last two bytes of ng_priv. no clue why 94 | struct { 95 | u8 ng_priv[30]; 96 | u8 _wtf1[18]; 97 | }; 98 | struct { 99 | u8 _wtf2[28]; 100 | u8 nand_hmac[20]; 101 | }; 102 | }; 103 | u8 nand_key[16]; 104 | u8 rng_key[16]; 105 | u32 unk1; 106 | u32 unk2; // 0x00000007 107 | } __attribute__((packed)) otp_t; 108 | 109 | typedef struct 110 | { 111 | u8 boot2version; 112 | u8 unknown1; 113 | u8 unknown2; 114 | u8 pad; 115 | u32 update_tag; 116 | u16 checksum; 117 | } __attribute__((packed)) eep_ctr_t; 118 | 119 | typedef struct 120 | { 121 | union { 122 | struct { 123 | u32 ms_key_id; 124 | u32 ca_key_id; 125 | u32 ng_key_id; 126 | u8 ng_sig[60]; 127 | eep_ctr_t counters[2]; 128 | u8 fill[0x18]; 129 | u8 korean_key[16]; 130 | }; 131 | u8 data[256]; 132 | }; 133 | } __attribute__((packed)) seeprom_t; 134 | 135 | void getotp(otp_t *otp); 136 | void getseeprom(seeprom_t *seeprom); 137 | void getMiniGitVer(char *buf, u16 len); 138 | 139 | void aes_reset(void); 140 | void aes_set_key(u8 *key); 141 | void aes_set_iv(u8 *iv); 142 | void aes_decrypt(u8 *src, u8 *dst, u32 blocks, u8 keep_iv); 143 | 144 | void nand_reset(void); 145 | u32 nand_getid(void); 146 | u8 nand_status(void); 147 | int nand_read(u32 pageno, void *data, void *ecc); 148 | void nand_write(u32 pageno, void *data, void *ecc); 149 | void nand_erase(u32 pageno); 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /input.c: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Input-handling functions for BootMii. Inspired by GC_PAD.c from GCLIB. 6 | 7 | Copyright (C) 2008, 2009 Haxx Enterprises 8 | Copyright (C) 2009 Andre Heider "dhewg" 9 | Copyright (C) 2009 John Kelley 10 | Copyright (C) 2009 bLAStY 11 | 12 | # This code is licensed to you under the terms of the GNU GPL, version 2; 13 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 14 | */ 15 | 16 | #include "powerpc.h" 17 | #include "input.h" 18 | #include "string.h" 19 | #include "console.h" 20 | 21 | #define PADREG(x) (0xCD006400 + (x)*4) 22 | 23 | static GC_Pad _pad; 24 | 25 | static void gcpad_init(void) { 26 | write32(PADREG(0), 0x00400300); // read pad on channel 1 27 | write32(PADREG(3), 0x00400300); 28 | write32(PADREG(6), 0x00400300); 29 | write32(PADREG(8), 0x00400300); 30 | write32(PADREG(12), 0x000701f0); // enable poll chan 1, X = 7, Y = 1 31 | write32(PADREG(14), 0x80000000); // transfer all buffer 32 | } 33 | 34 | static void gpio_init(void) { 35 | // setup power and eject button hollywood IRQ for PPC 36 | mask32(0x0d8000fc, 0, 0x41); // set GPIO owner to PPC 37 | mask32(0x0d80003c, 1<<10, 0); 38 | mask32(0x0d800034, 0, 1<<10); 39 | mask32(0x0d8000d4, 0, 0x41); 40 | mask32(0x0d8000cc, 0, 0x41); 41 | } 42 | 43 | void input_init(void) { 44 | memset(&_pad, 0, sizeof(GC_Pad)); 45 | 46 | gpio_init(); 47 | gcpad_init(); 48 | 49 | // Check for any pending GPIO irq's, which should be ACK'd so we don't get ghost presses later. 50 | // Try over and over again, until we are out of them. 51 | while (read32(0x0d800030) & (1<<10)) { 52 | if (read32(0x0d8000f0) & 1) { 53 | while(read32(0x0d8000c8) & 1); 54 | write32(0x0d8000d0, 1); 55 | } else if (read32(0x0d8000f0) & 0x40) { 56 | write32(0x0d8000d0, 0x40); 57 | } 58 | 59 | write32(0x0d800030, 1<<10); 60 | } 61 | 62 | // No IRQ's left to be ACK'd, continue our business. 63 | } 64 | 65 | u16 pad_read(GC_Pad *pad, int chan) { 66 | u32 pdata = read32(PADREG(3 * chan + 1)); 67 | u32 pdata2 = read32(PADREG(3 * chan + 2)); 68 | 69 | u16 btns = pdata >> 16; 70 | 71 | if (pad) { 72 | u16 prev = pad->btns_held; 73 | 74 | pad->btns_held = btns; 75 | pad->btns_up = prev & ~btns; 76 | pad->btns_down = btns & (btns ^ prev); 77 | 78 | pad->x = 128 + ((pdata >> 8) & 0xff); 79 | pad->y = 128 - (pdata & 0xff); 80 | 81 | pad->cx = 128 + (pdata2 >> 24); 82 | pad->cy = 128 - ((pdata2 >> 16) & 0xff); 83 | pad->l = (pdata2 >> 8) & 0xff; 84 | pad->r = pdata2 & 0xff; 85 | 86 | return pad->btns_down; 87 | } 88 | 89 | return btns; 90 | } 91 | 92 | #define LONG_PRESS_USEC 800000 // 0.7 seconds 93 | 94 | #define RST_DOWN !((read32(0x0C003000) >> 16) & 1) 95 | 96 | u16 gpio_read(void) { 97 | u16 res = 0; 98 | u32 irq_flag = 0; 99 | u64 press_start; 100 | 101 | // while reset is signalled 102 | if (RST_DOWN) { 103 | res |= GPIO_RESET; 104 | 105 | press_start = mftb_usec(); 106 | 107 | int toggle = 0; 108 | 109 | // wait for user to release the button 110 | while (RST_DOWN) { 111 | if (res & GPIO_RESET_LP) { 112 | toggle = !toggle; 113 | console_set_blinker(toggle); 114 | } else { 115 | if (mftb_usec() - press_start >= LONG_PRESS_USEC) { 116 | res |= GPIO_RESET_LP; 117 | } 118 | } 119 | } 120 | 121 | console_set_blinker(0); 122 | } 123 | 124 | if (read32(0x0d800030) & (1<<10)) { 125 | irq_flag = read32(0x0d8000f0); 126 | 127 | if (irq_flag & 1) { 128 | res |= GPIO_POWER; 129 | 130 | while(read32(0x0d8000c8) & 1); 131 | write32(0x0d8000d0, 1); 132 | } else if (irq_flag & 0x40) { 133 | res |= GPIO_EJECT; 134 | 135 | while(read32(0x0d8000c8) & 0x40); 136 | write32(0x0d8000d0, 0x40); 137 | } 138 | 139 | write32(0x0d800030, 1<<10); // ack GPIO irq 140 | } 141 | 142 | return res; 143 | } 144 | 145 | u16 input_read(void) { 146 | return pad_read(&_pad, 0) | gpio_read(); 147 | } 148 | 149 | u16 input_wait(void) { 150 | u16 res; 151 | 152 | do { 153 | usleep(INPUT_WAIT_CYCLE_DELAY); 154 | res = input_read(); 155 | } while (!res); 156 | 157 | return res; 158 | } 159 | 160 | -------------------------------------------------------------------------------- /browse.c: -------------------------------------------------------------------------------- 1 | 2 | #include "browse.h" 3 | #include "fatfs/ff.h" 4 | #include "malloc.h" 5 | #include "log.h" 6 | #include "powerpc_elf.h" 7 | 8 | char *browse_menu_entries[CONSOLE_LINES-HELP_LINES-HEAD_LINES-2]; 9 | int browse_menu_entries_count = 0; 10 | 11 | char browse_current_path[4096]; 12 | 13 | // used by FatFS 14 | PARTITION VolToPart[FF_VOLUMES] = { 15 | {0, 1}, /* "0:" ==> Physical drive 0, 1st partition */ 16 | {0, 2}, /* "1:" ==> Physical drive 0, 2nd partition */ 17 | {0, 3}, /* "2:" ==> Physical drive 0, 3rd partition */ 18 | {0, 4} /* "3:" ==> Physical drive 0, 4th partition */ 19 | }; 20 | 21 | static void browse_append(const char *name, int is_directory) { 22 | // stop ingurgitating menu entries 23 | if (browse_menu_entries_count == sizeof(browse_menu_entries)) 24 | return; 25 | 26 | if (!is_directory) 27 | browse_menu_entries[browse_menu_entries_count++] = strdup(name); 28 | else 29 | browse_menu_entries[browse_menu_entries_count++] = strcat(name, "/"); 30 | } 31 | 32 | static void menu_browse_leave(void) { 33 | menu_selection = old_menu_selection; 34 | menu_clear_entries(); 35 | menu_draw_entries_and_help(); 36 | } 37 | 38 | int menu_browse() { 39 | DIR dirs; 40 | FILINFO Fno; 41 | //NOTE: menu entries must have already been free'd on entry 42 | 43 | FRESULT res = f_opendir(&dirs, browse_current_path); 44 | if (res != FR_OK) { 45 | log_printf("failed to open directory '%s': %d\n", browse_current_path, res); 46 | sleep(4); 47 | 48 | menu_browse_leave(); 49 | return (int)res; 50 | } 51 | 52 | // add first entry to go back one level 53 | browse_append("..", 0); 54 | 55 | while (((res = f_readdir(&dirs, &Fno)) == FR_OK) && Fno.fname[0]) { 56 | if (Fno.fattrib & AM_DIR) { 57 | browse_append(Fno.fname, 1); 58 | } else { 59 | browse_append(Fno.fname, 0); 60 | } 61 | } 62 | if (res != FR_OK) { 63 | log_printf("failed to read directory '%s': %d\n", browse_current_path, res); 64 | sleep(3); 65 | } 66 | 67 | // add an extra entry to go back - it uses DISP_LEFT character code point 68 | browse_append("\x1b Back to menu", 0); 69 | 70 | // draw the new menu 71 | menu_selection = 0; 72 | menu_clear_entries(); 73 | menu_draw_entries_and_help(); 74 | 75 | // return non-zero so that input loop continues 76 | return 1; 77 | } 78 | 79 | static void free_browse_menu() { 80 | int i; 81 | // free all browse menu entries 82 | for(i=0;i 6 | Copyright (C) 2009 Haxx Enterprises 7 | Copyright (C) 2009 John Kelley 8 | Copyright (C) 2008, 2009 Sven Peter 9 | 10 | # This code is licensed to you under the terms of the GNU GPL, version 2; 11 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 12 | */ 13 | 14 | #include "powerpc.h" 15 | #include "ipc.h" 16 | #include "mini_ipc.h" 17 | #include "string.h" 18 | 19 | int ipc_powerpc_boot(const void *addr, u32 len) 20 | { 21 | ipc_request *req; 22 | 23 | sync_after_write(addr, len); 24 | req = ipc_exchange(IPC_PPC_BOOT, 3, 0, virt_to_phys(addr), len); 25 | return req->args[0]; 26 | } 27 | 28 | u32 boot2_run(u32 hi, u32 lo) 29 | { 30 | ipc_request * req; 31 | req = ipc_exchange(IPC_BOOT2_RUN, 2, hi, lo); 32 | return req->args[0]; 33 | } 34 | 35 | tmd *boot2_tmd(void) 36 | { 37 | tmd *ret = phys_to_virt(ipc_exchange(IPC_BOOT2_TMD, 0)->args[0]); 38 | sync_before_read(ret, sizeof(tmd)); 39 | return ret; 40 | } 41 | 42 | void getotp(otp_t *otp) 43 | { 44 | sync_before_read(otp, sizeof(*otp)); 45 | ipc_exchange(IPC_KEYS_GETOTP, 1, virt_to_phys(otp)); 46 | } 47 | 48 | void getMiniGitVer(char *buf, u16 len) 49 | { 50 | if (len < 32) 51 | { 52 | memset((void *)buf, 0, 32); 53 | return; 54 | } 55 | sync_before_read(buf, len); 56 | ipc_exchange(IPC_SYS_GETGITS, 1, virt_to_phys(buf)); 57 | } 58 | 59 | void getseeprom(seeprom_t *seeprom) 60 | { 61 | sync_before_read(seeprom, sizeof(*seeprom)); 62 | ipc_exchange(IPC_KEYS_GETEEP, 1, virt_to_phys(seeprom)); 63 | } 64 | 65 | void aes_reset(void) 66 | { 67 | ipc_exchange(IPC_AES_RESET, 0); 68 | } 69 | 70 | void aes_set_key(u8 *key) 71 | { 72 | u32 *keyptr = (u32 *)key; 73 | ipc_exchange(IPC_AES_SETKEY, 4, keyptr[0], keyptr[1], keyptr[2], keyptr[3]); 74 | } 75 | 76 | void aes_set_iv(u8 *iv) 77 | { 78 | u32 *ivptr = (u32 *)iv; 79 | ipc_exchange(IPC_AES_SETIV, 4, ivptr[0], ivptr[1], ivptr[2], ivptr[3]); 80 | } 81 | 82 | void aes_decrypt(u8 *src, u8 *dst, u32 blocks, u8 keep_iv) 83 | { 84 | sync_after_write(src, (blocks+1)*16); 85 | ipc_exchange(IPC_AES_DECRYPT, 4, virt_to_phys(src), virt_to_phys(dst), blocks, keep_iv); 86 | sync_before_read(dst, (blocks+1)*16); 87 | } 88 | 89 | void nand_reset(void) 90 | { 91 | ipc_exchange(IPC_NAND_RESET, 0); 92 | } 93 | 94 | u32 nand_getid(void) 95 | { 96 | static u8 idbuf[64] __attribute__((aligned(64))); 97 | 98 | ipc_exchange(IPC_NAND_GETID, 1, virt_to_phys(&idbuf)); 99 | sync_before_read(idbuf, 0x40); 100 | 101 | return idbuf[0] << 24 | idbuf[1] << 16 | idbuf[2] << 8 | idbuf[3]; 102 | } 103 | 104 | u8 nand_status(void) 105 | { 106 | static u8 buf[64] __attribute__((aligned(64))); 107 | 108 | ipc_exchange(IPC_NAND_STATUS, 1, virt_to_phys(&buf)); 109 | sync_before_read(buf, 0x40); 110 | 111 | return buf[0]; 112 | } 113 | 114 | int nand_read(u32 pageno, void *data, void *ecc) 115 | { 116 | if (data) 117 | sync_before_read(data, 0x800); 118 | if (ecc) 119 | sync_before_read(ecc, 0x40); 120 | return ipc_exchange(IPC_NAND_READ, 3, pageno, 121 | (!data ? (u32)-1 : virt_to_phys(data)), 122 | (!ecc ? (u32)-1 : virt_to_phys(ecc)))->args[0]; 123 | } 124 | 125 | void nand_write(u32 pageno, void *data, void *ecc) 126 | { 127 | if (data) 128 | sync_after_write(data, 0x800); 129 | if (ecc) 130 | sync_after_write(ecc, 0x40); 131 | ipc_exchange(IPC_NAND_WRITE, 3, pageno, 132 | (!data ? (u32)-1 : virt_to_phys(data)), 133 | (!ecc ? (u32)-1 : virt_to_phys(ecc))); 134 | } 135 | 136 | void nand_erase(u32 pageno) 137 | { 138 | ipc_exchange(IPC_NAND_ERASE, 1, pageno); 139 | } 140 | 141 | int sd_mount(void) 142 | { 143 | return ipc_exchange(IPC_SDMMC_ACK, 0)->args[0]; 144 | } 145 | 146 | int sd_get_state(void) 147 | { 148 | return ipc_exchange(IPC_SDMMC_STATE, 0)->args[0]; 149 | } 150 | 151 | int sd_protected(void) 152 | { 153 | // return (ipc_exchange(IPC_SD_GETSTATE, 0)->args[0] & SDHC_WRITE_PROTECT) == SDHC_WRITE_PROTECT; 154 | return 0; 155 | } 156 | 157 | int sd_select(void) 158 | { 159 | return 1; 160 | // return ipc_exchange(IPC_SD_SELECT, 0)->args[0]; 161 | } 162 | 163 | int sd_read(u32 start_block, u32 blk_cnt, void *buffer) 164 | { 165 | int retval; 166 | sync_before_read(buffer, blk_cnt * 512); 167 | retval = ipc_exchange(IPC_SDMMC_READ, 3, start_block, blk_cnt, virt_to_phys(buffer))->args[0]; 168 | return retval; 169 | } 170 | 171 | int sd_write(u32 start_block, u32 blk_cnt, const void *buffer) 172 | { 173 | int retval; 174 | sync_after_write(buffer, blk_cnt * 512); 175 | retval = ipc_exchange(IPC_SDMMC_WRITE, 3, start_block, blk_cnt, virt_to_phys(buffer))->args[0]; 176 | 177 | return retval; 178 | } 179 | 180 | u32 sd_getsize(void) 181 | { 182 | return ipc_exchange(IPC_SDMMC_SIZE, 0)->args[0]; 183 | } 184 | 185 | -------------------------------------------------------------------------------- /diskio.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ 3 | /*-----------------------------------------------------------------------*/ 4 | /* If a working storage control module is available, it should be */ 5 | /* attached to the FatFs via a glue function rather than modifying it. */ 6 | /* This is an example of glue functions to attach various exsisting */ 7 | /* storage control modules to the FatFs module with a defined API. */ 8 | /*-----------------------------------------------------------------------*/ 9 | 10 | #include "fatfs/diskio.h" /* FatFs lower layer API */ 11 | #include "mini_ipc.h" 12 | #include "string.h" 13 | 14 | static u8 *sector_buffer[512] __attribute__((aligned(32))); 15 | 16 | /*-----------------------------------------------------------------------*/ 17 | /* Get Drive Status */ 18 | /*-----------------------------------------------------------------------*/ 19 | 20 | DSTATUS disk_status ( 21 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 22 | ) 23 | { 24 | // only SD supported 25 | if (pdrv != 0) 26 | return STA_NODISK; 27 | 28 | int state = sd_get_state(); 29 | 30 | switch (state) { 31 | case SDMMC_NO_CARD: 32 | return STA_NODISK; 33 | case SDMMC_NEW_CARD: 34 | return STA_NOINIT; 35 | } 36 | return 0; 37 | } 38 | 39 | 40 | 41 | /*-----------------------------------------------------------------------*/ 42 | /* Initialize a Drive */ 43 | /*-----------------------------------------------------------------------*/ 44 | 45 | DSTATUS disk_initialize (BYTE drv) 46 | { 47 | // only SD supported 48 | if (drv != 0) 49 | return STA_NODISK; 50 | 51 | int state = sd_get_state(); 52 | 53 | switch (state) { 54 | case SDMMC_NO_CARD: 55 | return STA_NODISK; 56 | 57 | case SDMMC_NEW_CARD: 58 | if (sd_mount()) 59 | return STA_NOINIT; 60 | else 61 | return 0; 62 | 63 | default: 64 | return 0; 65 | } 66 | } 67 | 68 | 69 | /*-----------------------------------------------------------------------*/ 70 | /* Read Sector(s) */ 71 | /*-----------------------------------------------------------------------*/ 72 | 73 | DRESULT disk_read ( 74 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 75 | BYTE *buff, /* Data buffer to store read data */ 76 | DWORD sector, /* Start sector in LBA */ 77 | UINT count /* Number of sectors to read */ 78 | ) 79 | { 80 | u32 i; 81 | DRESULT res; 82 | 83 | // only SD supported 84 | if (pdrv != 0) 85 | return STA_NODISK; 86 | 87 | if (count > 1 && ((u32) buff % 64) == 0) { 88 | if (sd_read(sector, count, buff) != 0) 89 | return RES_ERROR; 90 | return RES_OK; 91 | } 92 | 93 | res = RES_OK; 94 | for (i = 0; i < count; i++) { 95 | if (sd_read(sector + i, 1, sector_buffer) != 0) { 96 | res = RES_ERROR; 97 | break; 98 | } 99 | 100 | memcpy(buff + i * 512, sector_buffer, 512); 101 | } 102 | 103 | return res; 104 | } 105 | 106 | 107 | 108 | /*-----------------------------------------------------------------------*/ 109 | /* Write Sector(s) */ 110 | /*-----------------------------------------------------------------------*/ 111 | #if FF_FS_READONLY == 0 112 | DRESULT disk_write ( 113 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 114 | const BYTE *buff, /* Data to be written */ 115 | DWORD sector, /* Start sector in LBA */ 116 | UINT count /* Number of sectors to write */ 117 | ) 118 | { 119 | // only SD supported 120 | if (pdrv != 0) 121 | return STA_NODISK; 122 | 123 | if (count > 1 && ((u32) buff % 64) == 0) { 124 | if (sd_write(sector, count, buff) != 0) 125 | return RES_ERROR; 126 | return RES_OK; 127 | } 128 | 129 | u32 i; 130 | for (i = 0; i < count; i++) { 131 | memcpy(sector_buffer, buff + i * 512, 512); 132 | if (sd_write(sector + i, 1, sector_buffer) != 0) { 133 | return RES_ERROR; 134 | } 135 | } 136 | 137 | return RES_OK; 138 | } 139 | #endif /* _READONLY */ 140 | 141 | 142 | 143 | /*-----------------------------------------------------------------------*/ 144 | /* Miscellaneous Functions */ 145 | /*-----------------------------------------------------------------------*/ 146 | 147 | DRESULT disk_ioctl ( 148 | BYTE pdrv, /* Physical drive nmuber (0..) */ 149 | BYTE cmd, /* Control code */ 150 | void *buff /* Buffer to send/receive control data */ 151 | ) 152 | { 153 | // only SD supported 154 | if (pdrv != 0) 155 | return STA_NODISK; 156 | 157 | u32 *buff_u32 = (u32 *) buff; 158 | 159 | switch (cmd) { 160 | case CTRL_SYNC: 161 | return RES_OK; 162 | case GET_SECTOR_COUNT: 163 | *buff_u32 = sd_getsize(); 164 | return RES_OK; 165 | case GET_SECTOR_SIZE: 166 | *buff_u32 = 512; 167 | return RES_OK; 168 | break; 169 | case GET_BLOCK_SIZE: 170 | *buff_u32 = 512; 171 | return RES_OK; 172 | } 173 | 174 | return RES_PARERR; 175 | } 176 | 177 | -------------------------------------------------------------------------------- /ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2008, 2009 Haxx Enterprises 6 | Copyright (C) 2008, 2009 Hector Martin "marcan" 7 | Copyright (C) 2009 Andre Heider "dhewg" 8 | Copyright (C) 2009 John Kelley 9 | Copyright (C) 2008, 2009 Sven Peter 10 | 11 | # This code is licensed to you under the terms of the GNU GPL, version 2; 12 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 13 | */ 14 | 15 | #ifndef __IPC_H__ 16 | #define __IPC_H__ 17 | 18 | #include "types.h" 19 | 20 | /* TODO: It would be nice to somehow link this header file with mini/ipc.h. 21 | Until then, if you do make any changes here, you MUST make them here 22 | (or vice-versa). See warnings in mini/ipc.h. --bushing */ 23 | 24 | #define IPC_SYS_PING 0x01000000 25 | #define IPC_SYS_SLWPING 0x00000000 26 | #define IPC_SYS_JUMP 0x00000001 27 | #define IPC_SYS_GETVERS 0x00000002 28 | #define IPC_SYS_GETGITS 0x00000003 29 | 30 | #define IPC_SYS_WRITE32 0x01000100 31 | #define IPC_SYS_WRITE16 0x01000101 32 | #define IPC_SYS_WRITE8 0x01000102 33 | #define IPC_SYS_READ32 0x01000103 34 | #define IPC_SYS_READ16 0x01000104 35 | #define IPC_SYS_READ8 0x01000105 36 | #define IPC_SYS_SET32 0x01000106 37 | #define IPC_SYS_SET16 0x01000107 38 | #define IPC_SYS_SET8 0x01000108 39 | #define IPC_SYS_CLEAR32 0x01000109 40 | #define IPC_SYS_CLEAR16 0x0100010a 41 | #define IPC_SYS_CLEAR8 0x0100010b 42 | #define IPC_SYS_MASK32 0x0100010c 43 | #define IPC_SYS_MASK16 0x0100010d 44 | #define IPC_SYS_MASK8 0x0100010e 45 | 46 | #define IPC_NAND_RESET 0x00010000 47 | #define IPC_NAND_GETID 0x00010001 48 | #define IPC_NAND_READ 0x00010002 49 | #define IPC_NAND_WRITE 0x00010003 50 | #define IPC_NAND_ERASE 0x00010004 51 | #define IPC_NAND_STATUS 0x00010005 52 | //#define IPC_NAND_USER0 0x00018000 53 | //#define IPC_NAND_USER1 0x00018001 54 | // etc. 55 | 56 | #define IPC_SDMMC_ACK 0x00070000 57 | #define IPC_SDMMC_READ 0x00070001 58 | #define IPC_SDMMC_WRITE 0x00070002 59 | #define IPC_SDMMC_STATE 0x00070003 60 | #define IPC_SDMMC_SIZE 0x00070004 61 | 62 | #define IPC_SDHC_DISCOVER 0x00020000 63 | 64 | #define IPC_KEYS_GETOTP 0x00030000 65 | #define IPC_KEYS_GETEEP 0x00030001 66 | 67 | #define IPC_AES_RESET 0x00040000 68 | #define IPC_AES_SETIV 0x00040001 69 | #define IPC_AES_SETKEY 0x00040002 70 | #define IPC_AES_DECRYPT 0x00040003 71 | 72 | #define IPC_BOOT2_RUN 0x00050000 73 | #define IPC_BOOT2_TMD 0x00050001 74 | 75 | #define IPC_PPC_BOOT 0x00060000 76 | 77 | typedef struct { 78 | union { 79 | struct { 80 | u8 flags; 81 | u8 device; 82 | u16 req; 83 | }; 84 | u32 code; 85 | }; 86 | u32 tag; 87 | u32 args[6]; 88 | } ipc_request; 89 | 90 | extern void *mem2_boundary; 91 | 92 | int ipc_initialize(void); 93 | void ipc_shutdown(void); 94 | 95 | void ipc_post(u32 code, u32 tag, u32 num_args, ...); 96 | 97 | void ipc_flush(void); 98 | 99 | ipc_request *ipc_receive(void); 100 | ipc_request *ipc_receive_tagged(u32 code, u32 tag); 101 | 102 | ipc_request *ipc_exchange(u32 code, u32 num_args, ...); 103 | 104 | static inline void ipc_sys_write32(u32 addr, u32 x) 105 | { 106 | ipc_post(IPC_SYS_WRITE32, 0, 2, addr, x); 107 | } 108 | static inline void ipc_sys_write16(u32 addr, u16 x) 109 | { 110 | ipc_post(IPC_SYS_WRITE16, 0, 2, addr, x); 111 | } 112 | static inline void ipc_sys_write8(u32 addr, u8 x) 113 | { 114 | ipc_post(IPC_SYS_WRITE8, 0, 2, addr, x); 115 | } 116 | 117 | static inline u32 ipc_sys_read32(u32 addr) 118 | { 119 | return ipc_exchange(IPC_SYS_READ32, 1, addr)->args[0]; 120 | } 121 | static inline u16 ipc_sys_read16(u32 addr) 122 | { 123 | return ipc_exchange(IPC_SYS_READ16, 1, addr)->args[0]; 124 | } 125 | static inline u8 ipc_sys_read8(u32 addr) 126 | { 127 | return ipc_exchange(IPC_SYS_READ8, 1, addr)->args[0]; 128 | } 129 | 130 | static inline void ipc_sys_set32(u32 addr, u32 set) 131 | { 132 | ipc_post(IPC_SYS_SET32, 0, 2, addr, set); 133 | } 134 | static inline void ipc_sys_set16(u32 addr, u16 set) 135 | { 136 | ipc_post(IPC_SYS_SET16, 0, 2, addr, set); 137 | } 138 | static inline void ipc_sys_set8(u32 addr, u8 set) 139 | { 140 | ipc_post(IPC_SYS_SET8, 0, 2, addr, set); 141 | } 142 | 143 | static inline void ipc_sys_clear32(u32 addr, u32 clear) 144 | { 145 | ipc_post(IPC_SYS_CLEAR32, 0, 2, addr, clear); 146 | } 147 | static inline void ipc_sys_clear16(u32 addr, u16 clear) 148 | { 149 | ipc_post(IPC_SYS_CLEAR16, 0, 2, addr, clear); 150 | } 151 | static inline void ipc_sys_clear8(u32 addr, u8 clear) 152 | { 153 | ipc_post(IPC_SYS_CLEAR8, 0, 2, addr, clear); 154 | } 155 | 156 | static inline void ipc_sys_mask32(u32 addr, u32 clear, u32 set) 157 | { 158 | ipc_post(IPC_SYS_MASK32, 0, 3, addr, clear, set); 159 | } 160 | static inline void ipc_sys_mask16(u32 addr, u16 clear, u32 set) 161 | { 162 | ipc_post(IPC_SYS_MASK16, 0, 3, addr, clear, set); 163 | } 164 | static inline void ipc_sys_mask8(u32 addr, u8 clear, u32 set) 165 | { 166 | ipc_post(IPC_SYS_MASK8, 0, 3, addr, clear, set); 167 | } 168 | 169 | static inline void ipc_ping(void) 170 | { 171 | ipc_exchange(IPC_SYS_PING, 0); 172 | } 173 | 174 | static inline void ipc_slowping(void) 175 | { 176 | ipc_exchange(IPC_SYS_SLWPING, 0); 177 | } 178 | 179 | static inline u32 ipc_getvers(void) 180 | { 181 | return ipc_exchange(IPC_SYS_GETVERS, 0)->args[0]; 182 | } 183 | 184 | #endif 185 | 186 | -------------------------------------------------------------------------------- /gecko.c: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (c) 2008 Nuke - 6 | Copyright (C) 2008, 2009 Hector Martin "marcan" 7 | Copyright (C) 2009 Andre Heider "dhewg" 8 | 9 | # This code is licensed to you under the terms of the GNU GPL, version 2; 10 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 11 | */ 12 | 13 | #include "powerpc.h" 14 | #include "printf.h" 15 | 16 | #define EXI_REG_BASE 0xd806800 17 | #define EXI0_REG_BASE (EXI_REG_BASE+0x000) 18 | #define EXI1_REG_BASE (EXI_REG_BASE+0x014) 19 | #define EXI2_REG_BASE (EXI_REG_BASE+0x028) 20 | 21 | #define EXI0_CSR (EXI0_REG_BASE+0x000) 22 | #define EXI0_MAR (EXI0_REG_BASE+0x004) 23 | #define EXI0_LENGTH (EXI0_REG_BASE+0x008) 24 | #define EXI0_CR (EXI0_REG_BASE+0x00c) 25 | #define EXI0_DATA (EXI0_REG_BASE+0x010) 26 | 27 | #define EXI1_CSR (EXI1_REG_BASE+0x000) 28 | #define EXI1_MAR (EXI1_REG_BASE+0x004) 29 | #define EXI1_LENGTH (EXI1_REG_BASE+0x008) 30 | #define EXI1_CR (EXI1_REG_BASE+0x00c) 31 | #define EXI1_DATA (EXI1_REG_BASE+0x010) 32 | 33 | #define EXI2_CSR (EXI2_REG_BASE+0x000) 34 | #define EXI2_MAR (EXI2_REG_BASE+0x004) 35 | #define EXI2_LENGTH (EXI2_REG_BASE+0x008) 36 | #define EXI2_CR (EXI2_REG_BASE+0x00c) 37 | #define EXI2_DATA (EXI2_REG_BASE+0x010) 38 | 39 | int gecko_console_enabled = 0; 40 | 41 | static u32 _gecko_command(u32 command) { 42 | u32 i; 43 | // Memory Card Port B (Channel 1, Device 0, Frequency 3 (32Mhz Clock)) 44 | write32(EXI1_CSR, 0xd0); 45 | write32(EXI1_DATA, command); 46 | write32(EXI1_CR, 0x19); 47 | i = 1000; 48 | while ((read32(EXI1_CR) & 1) && (i--)); 49 | i = read32(EXI1_DATA); 50 | write32(EXI1_CSR, 0); 51 | return i; 52 | } 53 | 54 | static u32 _gecko_getid(void) 55 | { 56 | u32 i; 57 | // Memory Card Port B (Channel 1, Device 0, Frequency 3 (32Mhz Clock)) 58 | write32(EXI1_CSR, 0xd0); 59 | write32(EXI1_DATA, 0); 60 | write32(EXI1_CR, 0x19); 61 | while (read32(EXI1_CR) & 1); 62 | write32(EXI1_CR, 0x39); 63 | while (read32(EXI1_CR) & 1); 64 | i = read32(EXI1_DATA); 65 | write32(EXI1_CSR, 0); 66 | return i; 67 | } 68 | 69 | static u32 _gecko_sendbyte(char sendbyte) { 70 | u32 i = 0; 71 | i = _gecko_command(0xB0000000 | (sendbyte<<20)); 72 | if (i&0x04000000) 73 | return 1; // Return 1 if byte was sent 74 | return 0; 75 | } 76 | 77 | #if 0 78 | static u32 _gecko_recvbyte(char *recvbyte) { 79 | u32 i = 0; 80 | *recvbyte = 0; 81 | i = _gecko_command(0xA0000000); 82 | if (i&0x08000000) { 83 | // Return 1 if byte was received 84 | *recvbyte = (i>>16)&0xff; 85 | return 1; 86 | } 87 | return 0; 88 | } 89 | 90 | static u32 _gecko_checksend(void) { 91 | u32 i = 0; 92 | i = _gecko_command(0xC0000000); 93 | if (i&0x04000000) 94 | return 1; // Return 1 if safe to send 95 | return 0; 96 | } 97 | 98 | static u32 _gecko_checkrecv(void) { 99 | u32 i = 0; 100 | i = _gecko_command(0xD0000000); 101 | if (i&0x04000000) 102 | return 1; // Return 1 if safe to recv 103 | return 0; 104 | } 105 | 106 | static void gecko_flush(void) { 107 | char tmp; 108 | while(_gecko_recvbyte(&tmp)); 109 | } 110 | #endif 111 | 112 | static int gecko_isalive(void) { 113 | u32 i; 114 | 115 | i = _gecko_getid(); 116 | if (i != 0x00000000) 117 | return 0; 118 | 119 | i = _gecko_command(0x90000000); 120 | if ((i & 0xFFFF0000) != 0x04700000) 121 | return 0; 122 | 123 | return 1; 124 | } 125 | 126 | #if 0 127 | static int gecko_recvbuffer(void *buffer, u32 size) { 128 | u32 left = size; 129 | char *ptr = (char*)buffer; 130 | 131 | while(left>0) { 132 | if(!_gecko_recvbyte(ptr)) 133 | break; 134 | ptr++; 135 | left--; 136 | } 137 | return (size - left); 138 | } 139 | #endif 140 | 141 | int gecko_sendbuffer(const void *buffer, u32 size) { 142 | u32 left = size; 143 | char *ptr = (char*)buffer; 144 | 145 | while(left>0) { 146 | if(!_gecko_sendbyte(*ptr)) 147 | break; 148 | ptr++; 149 | left--; 150 | } 151 | return (size - left); 152 | } 153 | 154 | #if 0 155 | static int gecko_recvbuffer_safe(void *buffer, u32 size) { 156 | u32 left = size; 157 | char *ptr = (char*)buffer; 158 | 159 | while(left>0) { 160 | if(_gecko_checkrecv()) { 161 | if(!_gecko_recvbyte(ptr)) 162 | break; 163 | ptr++; 164 | left--; 165 | } 166 | } 167 | return (size - left); 168 | } 169 | 170 | static int gecko_sendbuffer_safe(const void *buffer, u32 size) { 171 | u32 left = size; 172 | char *ptr = (char*)buffer; 173 | 174 | while(left>0) { 175 | if(_gecko_checksend()) { 176 | if(!_gecko_sendbyte(*ptr)) 177 | break; 178 | ptr++; 179 | left--; 180 | } 181 | } 182 | return (size - left); 183 | } 184 | #endif 185 | 186 | void gecko_init(void) 187 | { 188 | // unlock EXI 189 | write32(0x0d00643c, 0); 190 | 191 | write32(EXI0_CSR, 0); 192 | write32(EXI1_CSR, 0); 193 | write32(EXI2_CSR, 0); 194 | write32(EXI0_CSR, 0x2000); 195 | write32(EXI0_CSR, 3<<10); 196 | write32(EXI1_CSR, 3<<10); 197 | 198 | if (!gecko_isalive()) 199 | return; 200 | 201 | gecko_console_enabled = 1; 202 | } 203 | 204 | int gecko_printf(const char *fmt, ...) { 205 | if (!gecko_console_enabled) 206 | return 0; 207 | 208 | va_list args; 209 | char buffer[1024]; 210 | int i; 211 | 212 | va_start(args, fmt); 213 | i = vsnprintf(buffer, sizeof(buffer)-1, fmt, args); 214 | va_end(args); 215 | 216 | return gecko_sendbuffer(buffer, i); 217 | } 218 | 219 | -------------------------------------------------------------------------------- /fatfs/ffsystem.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------*/ 2 | /* Sample code of OS dependent controls for FatFs */ 3 | /* (C)ChaN, 2017 */ 4 | /*------------------------------------------------------------------------*/ 5 | 6 | 7 | #include "ff.h" 8 | 9 | 10 | 11 | #if FF_USE_LFN == 3 /* Dynamic memory allocation */ 12 | 13 | /*------------------------------------------------------------------------*/ 14 | /* Allocate a memory block */ 15 | /*------------------------------------------------------------------------*/ 16 | 17 | void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */ 18 | UINT msize /* Number of bytes to allocate */ 19 | ) 20 | { 21 | return malloc(msize); /* Allocate a new memory block with POSIX API */ 22 | } 23 | 24 | 25 | /*------------------------------------------------------------------------*/ 26 | /* Free a memory block */ 27 | /*------------------------------------------------------------------------*/ 28 | 29 | void ff_memfree ( 30 | void* mblock /* Pointer to the memory block to free */ 31 | ) 32 | { 33 | free(mblock); /* Free the memory block with POSIX API */ 34 | } 35 | 36 | #endif 37 | 38 | 39 | 40 | #if FF_FS_REENTRANT /* Mutal exclusion */ 41 | 42 | /*------------------------------------------------------------------------*/ 43 | /* Create a Synchronization Object 44 | /*------------------------------------------------------------------------*/ 45 | /* This function is called in f_mount() function to create a new 46 | / synchronization object for the volume, such as semaphore and mutex. 47 | / When a 0 is returned, the f_mount() function fails with FR_INT_ERR. 48 | */ 49 | 50 | //const osMutexDef_t Mutex[FF_VOLUMES]; /* CMSIS-RTOS */ 51 | 52 | 53 | int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */ 54 | BYTE vol, /* Corresponding volume (logical drive number) */ 55 | FF_SYNC_t *sobj /* Pointer to return the created sync object */ 56 | ) 57 | { 58 | /* Win32 */ 59 | *sobj = CreateMutex(NULL, FALSE, NULL); 60 | return (int)(*sobj != INVALID_HANDLE_VALUE); 61 | 62 | /* uITRON */ 63 | // T_CSEM csem = {TA_TPRI,1,1}; 64 | // *sobj = acre_sem(&csem); 65 | // return (int)(*sobj > 0); 66 | 67 | /* uC/OS-II */ 68 | // OS_ERR err; 69 | // *sobj = OSMutexCreate(0, &err); 70 | // return (int)(err == OS_NO_ERR); 71 | 72 | /* FreeRTOS */ 73 | // *sobj = xSemaphoreCreateMutex(); 74 | // return (int)(*sobj != NULL); 75 | 76 | /* CMSIS-RTOS */ 77 | // *sobj = osMutexCreate(Mutex + vol); 78 | // return (int)(*sobj != NULL); 79 | } 80 | 81 | 82 | /*------------------------------------------------------------------------*/ 83 | /* Delete a Synchronization Object */ 84 | /*------------------------------------------------------------------------*/ 85 | /* This function is called in f_mount() function to delete a synchronization 86 | / object that created with ff_cre_syncobj() function. When a 0 is returned, 87 | / the f_mount() function fails with FR_INT_ERR. 88 | */ 89 | 90 | int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */ 91 | FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ 92 | ) 93 | { 94 | /* Win32 */ 95 | return (int)CloseHandle(sobj); 96 | 97 | /* uITRON */ 98 | // return (int)(del_sem(sobj) == E_OK); 99 | 100 | /* uC/OS-II */ 101 | // OS_ERR err; 102 | // OSMutexDel(sobj, OS_DEL_ALWAYS, &err); 103 | // return (int)(err == OS_NO_ERR); 104 | 105 | /* FreeRTOS */ 106 | // vSemaphoreDelete(sobj); 107 | // return 1; 108 | 109 | /* CMSIS-RTOS */ 110 | // return (int)(osMutexDelete(sobj) == osOK); 111 | } 112 | 113 | 114 | /*------------------------------------------------------------------------*/ 115 | /* Request Grant to Access the Volume */ 116 | /*------------------------------------------------------------------------*/ 117 | /* This function is called on entering file functions to lock the volume. 118 | / When a 0 is returned, the file function fails with FR_TIMEOUT. 119 | */ 120 | 121 | int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */ 122 | FF_SYNC_t sobj /* Sync object to wait */ 123 | ) 124 | { 125 | /* Win32 */ 126 | return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0); 127 | 128 | /* uITRON */ 129 | // return (int)(wai_sem(sobj) == E_OK); 130 | 131 | /* uC/OS-II */ 132 | // OS_ERR err; 133 | // OSMutexPend(sobj, FF_FS_TIMEOUT, &err)); 134 | // return (int)(err == OS_NO_ERR); 135 | 136 | /* FreeRTOS */ 137 | // return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); 138 | 139 | /* CMSIS-RTOS */ 140 | // return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK); 141 | } 142 | 143 | 144 | /*------------------------------------------------------------------------*/ 145 | /* Release Grant to Access the Volume */ 146 | /*------------------------------------------------------------------------*/ 147 | /* This function is called on leaving file functions to unlock the volume. 148 | */ 149 | 150 | void ff_rel_grant ( 151 | FF_SYNC_t sobj /* Sync object to be signaled */ 152 | ) 153 | { 154 | /* Win32 */ 155 | ReleaseMutex(sobj); 156 | 157 | /* uITRON */ 158 | // sig_sem(sobj); 159 | 160 | /* uC/OS-II */ 161 | // OSMutexPost(sobj); 162 | 163 | /* FreeRTOS */ 164 | // xSemaphoreGive(sobj); 165 | 166 | /* CMSIS-RTOS */ 167 | // osMutexRelease(sobj); 168 | } 169 | 170 | #endif 171 | 172 | -------------------------------------------------------------------------------- /menu_render.c: -------------------------------------------------------------------------------- 1 | 2 | #include "menu_render.h" 3 | #include "console_common.h" 4 | #include "raster.h" 5 | #include "browse.h" 6 | 7 | extern unsigned char gumboot_logo_pixels[]; 8 | 9 | raster gumboot_logo; 10 | 11 | int old_menu_selection; 12 | int menu_selection = 0; 13 | 14 | const char top_right_corner = 191, 15 | bottom_left_corner = 192, 16 | horiz_line = 196, 17 | bottom_right_corner = 217, 18 | top_left_corner = 218, 19 | vert_line = 179; 20 | 21 | void draw_box_at(int x, int y, int w, int h) { 22 | int base_x = x; 23 | int max_x = x+w-1, max_y=y+h-1; 24 | 25 | if ((h<2) || (w<2)) 26 | return; 27 | 28 | // draw top of the box 29 | gfx_printch_at(x, y, top_left_corner); 30 | for(x++;xhelp_text) { 108 | menu_draw_default_help(); 109 | return; 110 | } 111 | 112 | select_font(FONT_HELPTEXT); 113 | gfx_print_at(1, BOX_H+HEAD_LINES, sel->help_text); 114 | } 115 | 116 | void menu_draw_entries_and_help(void) { 117 | int max; 118 | if (browse_menu_entries_count) { 119 | max = browse_menu_entries_count; 120 | } else { 121 | max = config_entries_count; 122 | } 123 | int i; 124 | 125 | for(i=0;iwidth)/2, (RESOLUTION_H-menu_splash->height)/2, *menu_splash, config_color_normal[1]); 175 | sleep(4); 176 | }*/ 177 | } 178 | 179 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2008, 2009 Haxx Enterprises 6 | Copyright (C) 2009 Andre Heider "dhewg" 7 | Copyright (C) 2008, 2009 Hector Martin "marcan" 8 | Copyright (C) 2008, 2009 Sven Peter 9 | Copyright (C) 2009 John Kelley 10 | Copyright (C) 2017 neagix 11 | 12 | # This code is licensed to you under the terms of the GNU GPL, version 2; 13 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 14 | */ 15 | 16 | #include "powerpc.h" 17 | #include "string.h" 18 | #include "ipc.h" 19 | #include "gecko.h" 20 | #include "mini_ipc.h" 21 | #include "nandfs.h" 22 | #include "fatfs/ff.h" 23 | #include "malloc.h" 24 | #include "fatfs/diskio.h" 25 | #include "printf.h" 26 | #include "video_low.h" 27 | #include "input.h" 28 | #include "console.h" 29 | #include "menu.h" 30 | #include "menu_render.h" 31 | #include "config.h" 32 | #include "log.h" 33 | #include "utils.h" 34 | #include "lodepng/lodepng.h" 35 | #include "raster.h" 36 | 37 | void flush_logs_and_enable_gfx(void); 38 | 39 | #define MINIMUM_MINI_VERSION 0x00010001 40 | 41 | int main(void) 42 | { 43 | exception_init(); 44 | dsp_reset(); 45 | 46 | // clear interrupt mask 47 | write32(0x0c003004, 0); 48 | 49 | ipc_initialize(); 50 | ipc_slowping(); 51 | 52 | gecko_init(); 53 | 54 | // initialise backbuffer for our precious log messages 55 | if (log_init_bb()) { 56 | gecko_printf("could not allocate log backbuffer\n"); 57 | powerpc_hang(); 58 | return -1; 59 | } 60 | 61 | // mount the first partition, where we expect to find gumboot/gumboot.lst 62 | int has_fs = 0; 63 | FATFS fatfs; 64 | FRESULT res = f_mount(&fatfs, "0:", 1); 65 | if (res == FR_OK) { 66 | has_fs = 1; 67 | 68 | u32 read; 69 | char *cfg_data = (char*)load_file(DEFAULT_LST, MAX_LST_SIZE, &read); 70 | if (cfg_data) { 71 | // terminate string 72 | cfg_data[read] = 0; 73 | 74 | if (config_load_from_buffer(cfg_data, read)) { 75 | // in case of error disable some features 76 | config_timeout = 0; 77 | config_nomenu = 0; 78 | } 79 | // error will be checked later on 80 | free(cfg_data); 81 | } 82 | } else { 83 | log_printf("could not mount first partition: %d\n", res); 84 | } 85 | 86 | input_init(); 87 | init_fb(config_vmode); 88 | clear_fb(black); 89 | 90 | VIDEO_Init(config_vmode); 91 | VIDEO_SetFrameBuffer(get_xfb()); 92 | 93 | // is this a gamecube? 94 | if (read32(0x0d800190) & 2) { 95 | log_printf("GameCube compatibility mode detected...\n"); 96 | } else { 97 | // Wii mode 98 | VISetupEncoder(); 99 | } 100 | 101 | u32 version = ipc_getvers(); 102 | u16 mini_version_major = version >> 16 & 0xFFFF; 103 | u16 mini_version_minor = version & 0xFFFF; 104 | 105 | // from now, console could be used 106 | // however 'gfx_console_init' is set to 1 later on 107 | 108 | if (version < MINIMUM_MINI_VERSION) { 109 | init_font(FONT_ERROR); 110 | init_font(FONT_NORMAL); 111 | flush_logs_and_enable_gfx(); 112 | 113 | log_printf("Mini version: %d.%0d\n", mini_version_major, mini_version_minor); 114 | log_printf("Sorry, this version of MINI (armboot.bin)\n" 115 | "is too old, please update to at least %d.%0d.\n", 116 | (MINIMUM_MINI_VERSION >> 16), (MINIMUM_MINI_VERSION & 0xFFFF)); 117 | 118 | powerpc_hang(); 119 | return 1; /* never reached */ 120 | } 121 | 122 | init_font(FONT_ERROR); 123 | init_font(FONT_NORMAL); 124 | init_font(FONT_HIGHLIGHT); 125 | init_font(FONT_HELPTEXT); 126 | init_font(FONT_HEADING); 127 | 128 | raster splash, *valid_splash = NULL; 129 | if (has_fs) { 130 | if (config_splashimage) { 131 | u32 read; 132 | void *png = load_file(config_splashimage, MAX_SPLASH_SIZE, &read); 133 | if (png) { 134 | // convert to raster 135 | int err = png_to_raster(png, read, splash); 136 | free(png); 137 | if (err) { 138 | log_printf("error %u: %s\n", err, lodepng_error_text(err)); 139 | } else { 140 | valid_splash = &splash; 141 | } 142 | } 143 | } 144 | int err = f_mount(NULL, "0:", 0); 145 | if (err) { 146 | log_printf("failed to unmount: %d\n", err); 147 | } 148 | } 149 | 150 | menu_selection = config_default; 151 | menu_init(valid_splash); 152 | 153 | if (config_nomenu) { 154 | if (!menu_activate()) 155 | goto quit; 156 | } 157 | 158 | menu_draw_head_and_box(mini_version_major, mini_version_minor); 159 | menu_draw_timeout(config_timeout); 160 | menu_draw_entries_and_help(); 161 | 162 | flush_logs_and_enable_gfx(); 163 | 164 | u64 start_time = mftb_usec(); 165 | int last_time_elapsed = 0; 166 | 167 | u16 btn; 168 | while (1) { 169 | do { 170 | if (config_timeout) { 171 | // update timeout as needed 172 | int new_time_elapsed = (int)((mftb_usec()-start_time)/1000000); 173 | 174 | if (new_time_elapsed != last_time_elapsed) { 175 | last_time_elapsed = new_time_elapsed; 176 | int left = config_timeout-last_time_elapsed; 177 | if (left <= 0) { 178 | // pretend there was an activation keypress 179 | btn = PAD_BUTTON_A; 180 | goto parse_input; 181 | } else { 182 | menu_update_timeout(left); 183 | } 184 | } 185 | } 186 | 187 | usleep(INPUT_WAIT_CYCLE_DELAY); 188 | btn = input_read(); 189 | 190 | parse_input: 191 | // disable timeout sequence 192 | if ((btn != 0) && (last_time_elapsed > 1)) { 193 | config_timeout = 0; 194 | menu_clear_timeout(); 195 | } 196 | } while (!btn); 197 | 198 | if (btn & PAD_BUTTON_A) { 199 | if (!menu_activate()) 200 | goto quit; 201 | } else if (btn & PAD_BUTTON_DOWN) { 202 | menu_down(); 203 | } else if (btn & PAD_BUTTON_UP) { 204 | menu_up(); 205 | } 206 | } 207 | quit: 208 | powerpc_hang(); 209 | 210 | return 0; 211 | } 212 | 213 | void flush_logs_and_enable_gfx(void) { 214 | // do not buffer log entries anymore 215 | gfx_console_init = 1; 216 | 217 | // put all the backbuffer log lines below the menu entries 218 | console_move(0, HEAD_LINES + 1 + config_entries_count + 1); 219 | // flush log lines from the backbuffer - if any 220 | log_flush_bb(); 221 | log_free_bb(); 222 | } 223 | -------------------------------------------------------------------------------- /ipc.c: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | Requires mini. 4 | 5 | Copyright (C) 2008, 2009 Hector Martin "marcan" 6 | Copyright (C) 2009 Andre Heider "dhewg" 7 | Copyright (C) 2009 John Kelley 8 | 9 | # This code is licensed to you under the terms of the GNU GPL, version 2; 10 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 11 | */ 12 | 13 | #include "powerpc.h" 14 | #include "ipc.h" 15 | #include "gecko.h" 16 | #include "string.h" 17 | #include 18 | 19 | static volatile ipc_request *in_queue; 20 | static volatile ipc_request *out_queue; 21 | 22 | static int in_size; 23 | static int out_size; 24 | 25 | static int initialized = 0; 26 | 27 | static u16 out_head; 28 | static u16 in_tail; 29 | 30 | typedef const struct { 31 | char magic[3]; 32 | char version; 33 | void *mem2_boundary; 34 | volatile ipc_request *ipc_in; 35 | u32 ipc_in_size; 36 | volatile ipc_request *ipc_out; 37 | u32 ipc_out_size; 38 | } ipc_infohdr; 39 | 40 | static ipc_infohdr *infohdr; 41 | 42 | static u32 cur_tag; 43 | 44 | #define HW_PPC_REG_BASE 0xd000000 45 | 46 | #define HW_IPC_PPCMSG (HW_PPC_REG_BASE + 0x000) //PPC to ARM 47 | #define HW_IPC_PPCCTRL (HW_PPC_REG_BASE + 0x004) 48 | #define HW_IPC_ARMMSG (HW_PPC_REG_BASE + 0x008) //ARM to PPC 49 | 50 | #define IPC_CTRL_SEND 0x01 51 | // Set by peer to acknowledge a message. Write one to clear. 52 | #define IPC_CTRL_SENT 0x02 53 | // Set by peer to send a message. Write one to clear. 54 | #define IPC_CTRL_RECV 0x04 55 | // Write one acknowledge a message. Cleared when peer writes one to IPC_CTRL_SENT. 56 | #define IPC_CTRL_RECVD 0x08 57 | // Enable interrupt when a message is received 58 | #define IPC_CTRL_INT_RECV 0x10 59 | // Enable interrupt when a sent message is acknowledged 60 | #define IPC_CTRL_INT_SENT 0x20 61 | 62 | static inline u16 peek_outtail(void) 63 | { 64 | return read32(HW_IPC_ARMMSG) & 0xFFFF; 65 | } 66 | static inline u16 peek_inhead(void) 67 | { 68 | return read32(HW_IPC_ARMMSG) >> 16; 69 | } 70 | 71 | static inline void poke_intail(u16 num) 72 | { 73 | mask32(HW_IPC_PPCMSG, 0xFFFF, num); 74 | } 75 | static inline void poke_outhead(u16 num) 76 | { 77 | mask32(HW_IPC_PPCMSG, 0xFFFF0000, num<<16); 78 | } 79 | 80 | int ipc_initialize(void) 81 | { 82 | 83 | infohdr = (ipc_infohdr*)(read32(0x13fffffc)|0x80000000); 84 | sync_before_read((void*)infohdr, sizeof(ipc_infohdr)); 85 | 86 | gecko_printf("IPC: infoheader at %p %08x\n", infohdr); 87 | 88 | if(memcmp(infohdr->magic, "IPC", 3)) { 89 | gecko_printf("IPC: bad magic on info structure\n",infohdr); 90 | return -1; 91 | } 92 | if(infohdr->version != 1) { 93 | gecko_printf("IPC: unknown IPC version %d\n",infohdr->version); 94 | return -1; 95 | } 96 | 97 | in_queue = (void*)(((u32)infohdr->ipc_in)|0x80000000); 98 | out_queue = (void*)(((u32)infohdr->ipc_out)|0x80000000); 99 | 100 | in_size = infohdr->ipc_in_size; 101 | out_size = infohdr->ipc_out_size; 102 | 103 | in_tail = read32(HW_IPC_PPCMSG) & 0xffff; 104 | out_head = read32(HW_IPC_PPCMSG) >> 16; 105 | 106 | gecko_printf("IPC: initial in tail: %d, out head: %d\n", in_tail, out_head); 107 | 108 | cur_tag = 1; 109 | 110 | initialized = 1; 111 | return 0; 112 | } 113 | 114 | void ipc_shutdown(void) 115 | { 116 | if(!initialized) 117 | return; 118 | ipc_flush(); 119 | initialized = 0; 120 | } 121 | 122 | void ipc_vpost(u32 code, u32 tag, u32 num_args, va_list ap) 123 | { 124 | int arg = 0; 125 | int n = 0; 126 | 127 | if(!initialized) { 128 | gecko_printf("IPC: not inited\n"); 129 | return; 130 | } 131 | 132 | if(peek_inhead() == ((in_tail + 1)&(in_size-1))) { 133 | gecko_printf("IPC: in queue full, spinning\n"); 134 | while(peek_inhead() == ((in_tail + 1)&(in_size-1))) { 135 | usleep(10); 136 | if(n++ > 20000) { 137 | gecko_printf("IPC: ARM might be stuck, still waiting for inhead %d != %d\n", 138 | peek_inhead(), ((in_tail + 1)&(in_size-1))); 139 | n = 0; 140 | } 141 | } 142 | } 143 | in_queue[in_tail].code = code; 144 | in_queue[in_tail].tag = tag; 145 | while(num_args--) { 146 | in_queue[in_tail].args[arg++] = va_arg(ap, u32); 147 | } 148 | sync_after_write((void*)&in_queue[in_tail], 32); 149 | in_tail = (in_tail+1)&(in_size-1); 150 | poke_intail(in_tail); 151 | write32(HW_IPC_PPCCTRL, IPC_CTRL_SEND); 152 | } 153 | 154 | void ipc_post(u32 code, u32 tag, u32 num_args, ...) 155 | { 156 | va_list ap; 157 | 158 | if(num_args) 159 | va_start(ap, num_args); 160 | 161 | ipc_vpost(code, tag, num_args, ap); 162 | 163 | if(num_args) 164 | va_end(ap); 165 | } 166 | 167 | void ipc_flush(void) 168 | { 169 | int n = 0; 170 | if(!initialized) { 171 | gecko_printf("IPC: not inited\n"); 172 | return; 173 | } 174 | while(peek_inhead() != in_tail) { 175 | usleep(10); 176 | if(n++ > 20000) { 177 | gecko_printf("IPC: ARM might be stuck, still waiting for inhead %d == intail %d\n", 178 | peek_inhead(), in_tail); 179 | n = 0; 180 | } 181 | } 182 | } 183 | 184 | // last IPC message received, copied because we need to make space in the queue 185 | ipc_request req_recv; 186 | 187 | // since we're not using IRQs, we don't use the reception bell at all at the moment 188 | ipc_request *ipc_receive(void) 189 | { 190 | while(peek_outtail() == out_head); 191 | sync_before_read((void*)&out_queue[out_head], 32); 192 | req_recv = out_queue[out_head]; 193 | out_head = (out_head+1)&(out_size-1); 194 | poke_outhead(out_head); 195 | 196 | return &req_recv; 197 | } 198 | 199 | void ipc_process_unhandled(volatile ipc_request *rep) 200 | { 201 | gecko_printf("IPC: Unhandled message: %08x %08x [%08x %08x %08x %08x %08x %08x]\n", 202 | rep->code, rep->tag, rep->args[0], rep->args[1], rep->args[2], rep->args[3], 203 | rep->args[4], rep->args[5]); 204 | } 205 | 206 | ipc_request *ipc_receive_tagged(u32 code, u32 tag) 207 | { 208 | ipc_request *rep; 209 | rep = ipc_receive(); 210 | while(rep->code != code || rep->tag != tag) { 211 | ipc_process_unhandled(rep); 212 | rep = ipc_receive(); 213 | } 214 | return rep; 215 | } 216 | 217 | ipc_request *ipc_exchange(u32 code, u32 num_args, ...) 218 | { 219 | va_list ap; 220 | ipc_request *rep; 221 | 222 | if(num_args) 223 | va_start(ap, num_args); 224 | 225 | ipc_vpost(code, cur_tag, num_args, ap); 226 | 227 | if(num_args) 228 | va_end(ap); 229 | 230 | rep = ipc_receive_tagged(code, cur_tag); 231 | 232 | cur_tag++; 233 | return rep; 234 | } 235 | 236 | -------------------------------------------------------------------------------- /nandfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn IOS. 3 | Requires mini. 4 | 5 | NAND filesystem support 6 | 7 | Copyright (C) 2008, 2009 Sven Peter 8 | 9 | # This code is licensed to you under the terms of the GNU GPL, version 2; 10 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 11 | */ 12 | 13 | #include "powerpc.h" 14 | #include "ipc.h" 15 | #include "mini_ipc.h" 16 | #include "nandfs.h" 17 | #include "string.h" 18 | #include "gecko.h" 19 | 20 | #define PAGE_SIZE 2048 21 | #define NANDFS_FREE 0xFFFE 22 | 23 | static otp_t otp; 24 | 25 | struct _nandfs_file_node { 26 | char name[NANDFS_NAME_LEN]; 27 | u8 attr; 28 | u8 wtf; 29 | union { 30 | u16 first_child; 31 | u16 first_cluster; 32 | }; 33 | u16 sibling; 34 | u32 size; 35 | u32 uid; 36 | u16 gid; 37 | u32 dummy; 38 | } __attribute__((packed)); 39 | 40 | struct _nandfs_sffs { 41 | u8 magic[4]; 42 | u32 version; 43 | u32 dummy; 44 | 45 | u16 cluster_table[32768]; 46 | struct _nandfs_file_node files[6143]; 47 | } __attribute__((packed)); 48 | 49 | 50 | union _sffs_t { 51 | u8 buffer[16*8*2048]; 52 | struct _nandfs_sffs sffs; 53 | }; 54 | 55 | static union _sffs_t sffs __attribute__((aligned(32))); 56 | 57 | /*static u8 _sffs_buffer[16*8*2048] __attribute__((aligned(32))); 58 | static struct _nandfs_sffs *sffs = (struct _nandfs_sffs *)&_sffs_buffer;*/ 59 | static u8 buffer[8*2048] __attribute__((aligned(32))); 60 | static s32 initialized = 0; 61 | 62 | void nand_read_cluster(u32 pageno, u8 *buffer) 63 | { 64 | int i; 65 | for (i = 0; i < 8; i++) 66 | nand_read(pageno + i, buffer + (i * PAGE_SIZE), NULL); 67 | } 68 | 69 | void nand_read_decrypted_cluster(u32 pageno, u8 *buffer) 70 | { 71 | u8 iv[16] = {0,}; 72 | nand_read_cluster(pageno, buffer); 73 | 74 | aes_reset(); 75 | aes_set_iv(iv); 76 | aes_set_key(otp.nand_key); 77 | aes_decrypt(buffer, buffer, 0x400, 0); 78 | } 79 | 80 | s32 nandfs_initialize(void) 81 | { 82 | u32 i; 83 | u32 supercluster = 0; 84 | u32 supercluster_version = 0; 85 | 86 | getotp(&otp); 87 | 88 | nand_reset(); 89 | 90 | for(i = 0x7F00; i < 0x7fff; i++) { 91 | nand_read(i*8, sffs.buffer, NULL); 92 | if(memcmp(sffs.sffs.magic, "SFFS", 4) != 0) 93 | continue; 94 | if(supercluster == 0 || 95 | sffs.sffs.version > supercluster_version) { 96 | supercluster = i*8; 97 | supercluster_version = sffs.sffs.version; 98 | } 99 | } 100 | 101 | if(supercluster == 0) { 102 | gecko_printf("no supercluster found. " 103 | " your nand filesystem is seriously broken...\n"); 104 | return -1; 105 | } 106 | 107 | for(i = 0; i < 16; i++) { 108 | gecko_printf("reading...\n"); 109 | nand_read_cluster(supercluster + i*8, 110 | (sffs.buffer) + (i * PAGE_SIZE * 8)); 111 | } 112 | 113 | initialized = 1; 114 | return 0; 115 | } 116 | 117 | u32 nandfs_get_usage(void) { 118 | u32 i; 119 | int used_clusters = 0; 120 | for (i=0; i < sizeof(sffs.sffs.cluster_table) / sizeof(u16); i++) 121 | if(sffs.sffs.cluster_table[i] != NANDFS_FREE) used_clusters++; 122 | 123 | gecko_printf("Used clusters: %d\n", used_clusters); 124 | return 1000 * used_clusters / (sizeof(sffs.sffs.cluster_table)/sizeof(u16)); 125 | } 126 | 127 | s32 nandfs_open(struct nandfs_fp *fp, const char *path) 128 | { 129 | char *ptr, *ptr2; 130 | u32 len; 131 | struct _nandfs_file_node *cur = sffs.sffs.files; 132 | 133 | if (initialized != 1) 134 | return -1; 135 | 136 | memset(fp, 0, sizeof(*fp)); 137 | 138 | if(strcmp(cur->name, "/") != 0) { 139 | gecko_printf("your nandfs is corrupted. fixit!\n"); 140 | return -1; 141 | } 142 | 143 | cur = &sffs.sffs.files[cur->first_child]; 144 | 145 | ptr = (char *)path; 146 | do { 147 | ptr++; 148 | ptr2 = strchr(ptr, '/'); 149 | if (ptr2 == NULL) 150 | len = strlen(ptr); 151 | else { 152 | ptr2++; 153 | len = ptr2 - ptr - 1; 154 | } 155 | if (len > 12) 156 | { 157 | gecko_printf("invalid length: %s %s %s [%d]\n", 158 | ptr, ptr2, path, len); 159 | return -1; 160 | } 161 | 162 | for (;;) { 163 | if(ptr2 != NULL && strncmp(cur->name, ptr, len) == 0 164 | && strnlen(cur->name, 12) == len 165 | && (cur->attr&3) == 2 166 | && (s16)(cur->first_child&0xffff) != (s16)0xffff) { 167 | cur = &sffs.sffs.files[cur->first_child]; 168 | ptr = ptr2-1; 169 | break; 170 | } else if(ptr2 == NULL && 171 | strncmp(cur->name, ptr, len) == 0 && 172 | strnlen(cur->name, 12) == len && 173 | (cur->attr&3) == 1) { 174 | break; 175 | } else if((cur->sibling&0xffff) != 0xffff) { 176 | cur = &sffs.sffs.files[cur->sibling]; 177 | } else { 178 | return -1; 179 | } 180 | } 181 | 182 | } while(ptr2 != NULL); 183 | 184 | fp->first_cluster = cur->first_cluster; 185 | fp->cur_cluster = fp->first_cluster; 186 | fp->offset = 0; 187 | fp->size = cur->size; 188 | return 0; 189 | } 190 | 191 | s32 nandfs_read(void *ptr, u32 size, u32 nmemb, struct nandfs_fp *fp) 192 | { 193 | u32 total = size*nmemb; 194 | u32 copy_offset, copy_len; 195 | 196 | if (initialized != 1) 197 | return -1; 198 | 199 | if (fp->offset + total > fp->size) 200 | total = fp->size - fp->offset; 201 | 202 | if (total == 0) 203 | return 0; 204 | 205 | while(total > 0) { 206 | nand_read_decrypted_cluster(fp->cur_cluster*8, buffer); 207 | copy_offset = fp->offset % (PAGE_SIZE * 8); 208 | copy_len = (PAGE_SIZE * 8) - copy_offset; 209 | if(copy_len > total) 210 | copy_len = total; 211 | memcpy(ptr, buffer + copy_offset, copy_len); 212 | total -= copy_len; 213 | fp->offset += copy_len; 214 | 215 | if ((copy_offset + copy_len) >= (PAGE_SIZE * 8)) 216 | fp->cur_cluster = sffs.sffs.cluster_table[fp->cur_cluster]; 217 | } 218 | 219 | return size*nmemb; 220 | } 221 | 222 | s32 nandfs_seek(struct nandfs_fp *fp, s32 offset, u32 whence) 223 | { 224 | if (initialized != 1) 225 | return -1; 226 | 227 | switch (whence) { 228 | case NANDFS_SEEK_SET: 229 | if (offset < 0) 230 | return -1; 231 | if ((u32)offset > fp->size) 232 | return -1; 233 | 234 | fp->offset = offset; 235 | break; 236 | 237 | case NANDFS_SEEK_CUR: 238 | if ((fp->offset + offset) > fp->size || 239 | (s32)(fp->offset + offset) < 0) 240 | return -1; 241 | fp->offset += offset; 242 | break; 243 | 244 | case NANDFS_SEEK_END: 245 | default: 246 | if ((fp->size + offset) > fp->size || 247 | (s32)(fp->size + offset) < 0) 248 | return -1; 249 | fp->offset = fp->size + offset; 250 | break; 251 | } 252 | 253 | int skip = fp->offset; 254 | fp->cur_cluster = fp->first_cluster; 255 | while (skip > (2048*8)) { 256 | fp->cur_cluster = sffs.sffs.cluster_table[fp->cur_cluster]; 257 | skip -= 2048*8; 258 | } 259 | 260 | return 0; 261 | } 262 | 263 | -------------------------------------------------------------------------------- /powerpc_elf.c: -------------------------------------------------------------------------------- 1 | /* 2 | mini - a Free Software replacement for the Nintendo/BroadOn IOS. 3 | PowerPC ELF file loading 4 | 5 | Copyright (C) 2008, 2009 Hector Martin "marcan" 6 | Copyright (C) 2009 Andre Heider "dhewg" 7 | 8 | # This code is licensed to you under the terms of the GNU GPL, version 2; 9 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 10 | */ 11 | 12 | #include "types.h" 13 | #include "powerpc.h" 14 | #include "hollywood.h" 15 | #include "gecko.h" 16 | #include "fatfs/ff.h" 17 | #include "powerpc_elf.h" 18 | #include "elf.h" 19 | #include "malloc.h" 20 | #include "string.h" 21 | #include "mini_ipc.h" 22 | #include "log.h" 23 | 24 | #define PHDR_MAX 10 25 | 26 | static Elf32_Ehdr elfhdr; 27 | static Elf32_Phdr phdrs[PHDR_MAX]; 28 | 29 | int is_valid_elf(const char *path) 30 | { 31 | u32 read; 32 | FIL fd; 33 | FRESULT fres; 34 | 35 | fres = f_open(&fd, path, FA_READ); 36 | if (fres != FR_OK) { 37 | log_printf("could not open ELF %s: %d\n", path, fres); 38 | return fres; 39 | } 40 | 41 | fres = f_read(&fd, &elfhdr, sizeof(elfhdr), &read); 42 | if (fres != FR_OK) { 43 | log_printf("could not read ELF %s: %d\n", path, fres); 44 | f_close(&fd); 45 | return fres; 46 | } 47 | 48 | if (read != sizeof(elfhdr)) { 49 | log_printf("expected %d bytes read, but got %d\n", path, sizeof(elfhdr), read); 50 | 51 | f_close(&fd); 52 | return -100; 53 | } 54 | 55 | if (memcmp("\x7F" "ELF\x01\x02\x01\x00\x00",elfhdr.e_ident,9)) { 56 | log_printf("Invalid ELF header! 0x%02x 0x%02x 0x%02x 0x%02x\n",elfhdr.e_ident[0], elfhdr.e_ident[1], elfhdr.e_ident[2], elfhdr.e_ident[3]); 57 | 58 | f_close(&fd); 59 | return -101; 60 | } 61 | 62 | // entry point not checked here 63 | 64 | if (elfhdr.e_phoff == 0 || elfhdr.e_phnum == 0) { 65 | log_printf("ELF has no program headers!\n"); 66 | 67 | f_close(&fd); 68 | return -103; 69 | } 70 | 71 | if (elfhdr.e_phnum > PHDR_MAX) { 72 | log_printf("ELF has too many (%d) program headers!\n", elfhdr.e_phnum); 73 | 74 | f_close(&fd); 75 | return -104; 76 | } 77 | 78 | fres = f_lseek(&fd, elfhdr.e_phoff); 79 | if (fres != FR_OK) { 80 | log_printf("could not seek in ELF %s: %d\n", path, fres); 81 | 82 | f_close(&fd); 83 | return -fres; 84 | } 85 | 86 | fres = f_read(&fd, phdrs, sizeof(phdrs[0])*elfhdr.e_phnum, &read); 87 | if (fres != FR_OK) { 88 | log_printf("could not read headers from ELF %s: %d\n", path, fres); 89 | 90 | f_close(&fd); 91 | return -fres; 92 | } 93 | 94 | if (read != sizeof(phdrs[0])*elfhdr.e_phnum) { 95 | log_printf("expected %d bytes read from headers, but got %d\n", path, sizeof(phdrs[0])*elfhdr.e_phnum, read); 96 | 97 | f_close(&fd); 98 | return -105; 99 | } 100 | 101 | u16 count = elfhdr.e_phnum; 102 | Elf32_Phdr *phdr = phdrs; 103 | 104 | int found = 0; 105 | while (count--) { 106 | if (phdr->p_type == PT_LOAD) { 107 | found = 1; 108 | break; 109 | } 110 | phdr++; 111 | } 112 | if (!found) { 113 | log_printf("no PT_LOAD header found in ELF %s: %d\n", path, fres); 114 | 115 | f_close(&fd); 116 | return -200; 117 | } 118 | 119 | f_close(&fd); 120 | return 0; 121 | } 122 | 123 | static char *memstr(char *mem, unsigned int fsize, const char *s) { 124 | unsigned int i; 125 | int l = strlen(s); 126 | int match = 0; 127 | for(i=0;i span) 170 | return -3; 171 | memcpy(start, args, l); 172 | 173 | // blank rest of bootargs 174 | int i; 175 | for(i=l;i 6 | Copyright (C) 2009 John Kelley 7 | 8 | # This code is licensed to you under the terms of the GNU GPL, version 2; 9 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 10 | */ 11 | 12 | #include "powerpc.h" 13 | #include "video_low.h" 14 | #include "console.h" 15 | #include "string.h" 16 | #include "printf.h" 17 | #include "malloc.h" 18 | #include "config.h" 19 | 20 | #include 21 | 22 | #include "console_common.h" 23 | 24 | int gfx_console_init = 0; 25 | 26 | static u32 *xfb = NULL; 27 | static int y_add = 0; 28 | // current absolute cursor position 29 | static int console_pos = 0; 30 | 31 | rgb black = {.as_rgba = {0, 0, 0, 0xFF}}; 32 | 33 | u32 *font_yuv_normal[255], 34 | *font_yuv_highlight[255], 35 | *font_yuv_helptext[255], 36 | *font_yuv_heading[255], 37 | // used only to print log entries 38 | *font_yuv_error[255]; 39 | 40 | u32 **selected_font_yuv = NULL; 41 | 42 | u32 *get_xfb(void) { 43 | return xfb; 44 | } 45 | 46 | static void memcpy32(u32 *dst, u32 *src, u32 count) { 47 | while(count--) { 48 | *dst = *src; 49 | sync_after_write((const void *)dst, 4); 50 | 51 | dst++; 52 | src++; 53 | } 54 | } 55 | 56 | static void memset32(u32 *dst, u32 setval, u32 count) { 57 | while(count--) { 58 | *dst = setval; 59 | sync_after_write((const void *)dst, 4); 60 | 61 | dst++; 62 | } 63 | } 64 | 65 | u32 pal_idx(int i, u8 *pal, u8 *gfx) { 66 | u32 pidx = gfx[i]; 67 | pidx *= 3; 68 | 69 | return (pal[pidx+0] << 16) | (pal[pidx+1] << 8) | (pal[pidx+2]); 70 | } 71 | 72 | int make_yuv(rgb c1, rgb c2) { 73 | int y1, cb1, cr1, y2, cb2, cr2, cb, cr; 74 | 75 | y1 = (299 * c1.as_rgba.r + 587 * c1.as_rgba.g + 114 * c1.as_rgba.b) / 1000; 76 | cb1 = (-16874 * c1.as_rgba.r - 33126 * c1.as_rgba.g + 50000 * c1.as_rgba.b + 12800000) / 100000; 77 | cr1 = (50000 * c1.as_rgba.r - 41869 * c1.as_rgba.g - 8131 * c1.as_rgba.b + 12800000) / 100000; 78 | 79 | y2 = (299 * c2.as_rgba.r + 587 * c2.as_rgba.g + 114 * c2.as_rgba.b) / 1000; 80 | cb2 = (-16874 * c2.as_rgba.r - 33126 * c2.as_rgba.g + 50000 * c2.as_rgba.b + 12800000) / 100000; 81 | cr2 = (50000 * c2.as_rgba.r - 41869 * c2.as_rgba.g - 8131 * c2.as_rgba.b + 12800000) / 100000; 82 | 83 | cb = (cb1 + cb2) >> 1; 84 | cr = (cr1 + cr2) >> 1; 85 | 86 | return ((y1 << 24) | (cb << 16) | (y2 << 8) | cr); 87 | } 88 | 89 | void fill_rect(int x, int y, int w, int h, rgb rgbcol) { 90 | u32 *fb = xfb; 91 | u32 col = make_yuv(rgbcol, rgbcol); 92 | 93 | fb += ((y + y_add) * (RESOLUTION_W >> 1)); 94 | fb += (x >> 1); 95 | 96 | for(y = 0; y < h; y++) { 97 | memset32(fb, col, w >> 1); 98 | fb += (RESOLUTION_W >> 1); 99 | } 100 | } 101 | 102 | void gfx_draw_char(int dx, int dy, unsigned char c) { 103 | u32 y; 104 | u32 *fb = xfb; 105 | u32 *yuv_data = selected_font_yuv[ c ]; 106 | 107 | fb += ((dy + y_add) * (RESOLUTION_W >> 1)); 108 | fb += (dx >> 1); 109 | 110 | for(y = 0; y < CONSOLE_CHAR_HEIGHT; y++) { 111 | memcpy32(fb, yuv_data + ((CONSOLE_CHAR_WIDTH >> 1) * y), CONSOLE_CHAR_WIDTH >> 1); 112 | fb += (RESOLUTION_W >> 1); 113 | } 114 | } 115 | 116 | void scroll(void) { 117 | unsigned int y; 118 | u32 *fb = xfb; 119 | 120 | fb += ((CONSOLE_Y_OFFSET+y_add+CONSOLE_ROW_HEIGHT) * (RESOLUTION_W >> 1)); 121 | fb += (CONSOLE_X_OFFSET >> 1); 122 | 123 | for (y = 0; y < CONSOLE_LINES*CONSOLE_ROW_HEIGHT; y++) { 124 | memcpy32(fb - (CONSOLE_ROW_HEIGHT * RESOLUTION_W/2), fb, CONSOLE_WIDTH >> 1); 125 | fb += RESOLUTION_W/2; 126 | } 127 | 128 | fill_rect(CONSOLE_X_OFFSET, CONSOLE_Y_OFFSET+(CONSOLE_LINES-1)*CONSOLE_ROW_HEIGHT, 129 | CONSOLE_WIDTH, CONSOLE_ROW_HEIGHT, black); 130 | } 131 | 132 | void gfx_clear(int x, int y, int w, int h, rgb c) { 133 | fill_rect(CONSOLE_X_OFFSET + x*CONSOLE_CHAR_WIDTH, CONSOLE_Y_OFFSET+ y * CONSOLE_ROW_HEIGHT, 134 | w*CONSOLE_CHAR_WIDTH, h * CONSOLE_ROW_HEIGHT, c); 135 | } 136 | 137 | void gfx_print(const char *str, size_t len) { 138 | unsigned int i; 139 | 140 | for (i = 0; i < len; i++) { 141 | // special case: a newline forces to reposition on next line 142 | if (str[i] == '\n') { 143 | console_pos += (CONSOLE_COLUMNS - console_pos % CONSOLE_COLUMNS); 144 | } else { 145 | // increase absolute position by 1 146 | console_pos++; 147 | } 148 | // calculate new coordinates 149 | int x = console_pos % CONSOLE_COLUMNS; 150 | int y = console_pos / CONSOLE_COLUMNS; 151 | 152 | // did the line number increase? 153 | if (x == 0) { 154 | // is the new y coordinate overflowing height? 155 | if (y == CONSOLE_LINES) { 156 | scroll(); 157 | y = CONSOLE_LINES - 1; 158 | // adjust to new scrolled position 159 | console_pos = y * CONSOLE_COLUMNS + x; 160 | } 161 | } 162 | 163 | // nothing to draw for newlines 164 | if (str[i] == '\n') { 165 | continue; 166 | } 167 | 168 | int dx = CONSOLE_X_OFFSET + x * CONSOLE_CHAR_WIDTH; 169 | int dy = CONSOLE_Y_OFFSET + y * CONSOLE_ROW_HEIGHT; 170 | 171 | gfx_draw_char(dx, dy, str[i]); 172 | } 173 | } 174 | 175 | int gfx_printf(const char *fmt, ...) 176 | { 177 | va_list args; 178 | int i; 179 | 180 | va_start(args, fmt); 181 | i = vsnprintf(pf_buffer, sizeof(pf_buffer)-1, fmt, args); 182 | va_end(args); 183 | 184 | if (i > 0) { 185 | gfx_print(pf_buffer, i); 186 | } 187 | 188 | return i; 189 | } 190 | 191 | void internal_free_font(u32 *font_yuv[255]) { 192 | int i; 193 | 194 | for (i = 0; i < 255; i++) { 195 | free(font_yuv[i]); 196 | } 197 | } 198 | 199 | void font_to_yuv(u32 *font_yuv[255], rgb fg, rgb bg) { 200 | int i, x, y; 201 | 202 | for (i = 0; i < 255; i++) { 203 | font_yuv[i] = (u32*)malloc(8*CONSOLE_CHAR_HEIGHT*2); 204 | 205 | for (y = 0; y < CONSOLE_CHAR_HEIGHT; y++) { 206 | for (x = 0; x < CONSOLE_CHAR_WIDTH; x+=2) { 207 | rgb left, right; 208 | if (((console_font_8x16[(i*CONSOLE_CHAR_HEIGHT)+y] >> (CONSOLE_CHAR_WIDTH-1-x)) & 0x01) == 1) { 209 | left = fg; 210 | } else { 211 | left = bg; 212 | } 213 | 214 | if (((console_font_8x16[(i*CONSOLE_CHAR_HEIGHT)+y] >> (CONSOLE_CHAR_WIDTH-1-(x+1))) & 0x01) == 1) { 215 | right = fg; 216 | } else { 217 | right = bg; 218 | } 219 | 220 | font_yuv[i][(y<<2)+(x>>1)] = make_yuv(left, right); 221 | } 222 | } 223 | } 224 | } 225 | 226 | void free_font(int font) { 227 | switch (font) { 228 | case FONT_HEADING: 229 | internal_free_font(font_yuv_heading); 230 | break; 231 | case FONT_NORMAL: 232 | internal_free_font(font_yuv_normal); 233 | break; 234 | case FONT_HELPTEXT: 235 | internal_free_font(font_yuv_helptext); 236 | break; 237 | case FONT_HIGHLIGHT: 238 | internal_free_font(font_yuv_highlight); 239 | break; 240 | case FONT_ERROR: 241 | internal_free_font(font_yuv_error); 242 | break; 243 | } 244 | // PANIC! 245 | return; 246 | } 247 | 248 | static void internal_init_font(rgb c[2], u32 *font_yuv[255]) { 249 | // re-initialise color 250 | font_to_yuv(font_yuv, c[0], c[1]); 251 | } 252 | 253 | void init_fb(int vmode) { 254 | // default fonts setup before configuration is loaded 255 | // and used to display configuration load errors / other log errors 256 | selected_font_yuv = font_yuv_normal; 257 | 258 | switch(vmode) { 259 | case VIDEO_640X480_NTSCi_YUV16: 260 | case VIDEO_640X480_PAL60_YUV16: 261 | case VIDEO_640X480_NTSCp_YUV16: 262 | y_add = 0; 263 | break; 264 | 265 | case VIDEO_640X480_PAL50_YUV16: 266 | y_add = 48; 267 | break; 268 | } 269 | 270 | xfb = memalign(32, RESOLUTION_W * (RESOLUTION_H + (y_add*2)) * 2); 271 | } 272 | 273 | // does not take splash screen in account 274 | void clear_fb(rgb fill_rgb) { 275 | int i; 276 | u32 *fb; 277 | 278 | u32 fill_yuv = make_yuv(fill_rgb, fill_rgb); 279 | 280 | fb = xfb; 281 | for (i = 0; i < (RESOLUTION_H + (y_add*2)) * 2 * (RESOLUTION_W >> 1); i++) { 282 | *fb = fill_yuv; 283 | sync_after_write(fb, 4); 284 | fb++; 285 | } 286 | } 287 | 288 | void select_font(int font) { 289 | switch (font) { 290 | case FONT_HEADING: 291 | selected_font_yuv = font_yuv_heading; 292 | break; 293 | case FONT_NORMAL: 294 | selected_font_yuv = font_yuv_normal; 295 | break; 296 | case FONT_HELPTEXT: 297 | selected_font_yuv = font_yuv_helptext; 298 | break; 299 | case FONT_HIGHLIGHT: 300 | selected_font_yuv = font_yuv_highlight; 301 | break; 302 | case FONT_ERROR: 303 | selected_font_yuv = font_yuv_error; 304 | break; 305 | } 306 | } 307 | 308 | void init_font(int font) { 309 | switch (font) { 310 | case FONT_HEADING: 311 | internal_init_font(config_color_heading, font_yuv_heading); 312 | break; 313 | case FONT_NORMAL: 314 | internal_init_font(config_color_normal, font_yuv_normal); 315 | break; 316 | case FONT_HELPTEXT: 317 | internal_init_font(config_color_helptext, font_yuv_helptext); 318 | break; 319 | case FONT_HIGHLIGHT: 320 | internal_init_font(config_color_highlight, font_yuv_highlight); 321 | break; 322 | case FONT_ERROR: 323 | internal_init_font(color_error, font_yuv_error); 324 | break; 325 | } 326 | // PANIC! 327 | return; 328 | } 329 | 330 | void console_move(int x, int y) { 331 | console_pos = y * CONSOLE_COLUMNS + x; 332 | } 333 | 334 | // toggle a block sign on the top-right corner of the console screen 335 | void console_set_blinker(int status) { 336 | select_font(FONT_HEADING); 337 | if (status) 338 | gfx_printch_at(CONSOLE_COLUMNS-1, 0, 254); 339 | else 340 | gfx_printch_at(CONSOLE_COLUMNS-1, 0, ' '); 341 | } 342 | 343 | void console_blit(int dx, int dy, raster rst, rgb solid_bg, u32 *yuv_row) { 344 | u32 x, y; 345 | u32 *fb = xfb; 346 | u32 *pixel_data = (u32 *)rst.pixels; 347 | 348 | fb += ((dy + y_add) * (RESOLUTION_W >> 1)); 349 | fb += (dx >> 1); 350 | 351 | // allocate a buffer that will be used for the RGB->YUV conversion 352 | u32 row_len = rst.width >> 1; 353 | 354 | for(y = 0; y < rst.height; y++) { 355 | for (x = 0; x < rst.width; x+=2) { 356 | // convert two pixels from source into one destination pixels 357 | rgb left = {.as_u32 = pixel_data[x + y * rst.width]}; 358 | rgb right = {.as_u32 = pixel_data[x + 1 + y * rst.width]}; 359 | 360 | left = apply_alpha(left, solid_bg); 361 | right = apply_alpha(right, solid_bg); 362 | 363 | yuv_row[x >> 1] = make_yuv(left, right); 364 | } 365 | 366 | memcpy32(fb, yuv_row, row_len); 367 | fb += (RESOLUTION_W >> 1); 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /fatfs/00history.txt: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | Revision history of FatFs module 3 | ---------------------------------------------------------------------------- 4 | 5 | R0.00 (February 26, 2006) 6 | 7 | Prototype. 8 | 9 | 10 | 11 | R0.01 (April 29, 2006) 12 | 13 | The first release. 14 | 15 | 16 | 17 | R0.02 (June 01, 2006) 18 | 19 | Added FAT12 support. 20 | Removed unbuffered mode. 21 | Fixed a problem on small (<32M) partition. 22 | 23 | 24 | 25 | R0.02a (June 10, 2006) 26 | 27 | Added a configuration option (_FS_MINIMUM). 28 | 29 | 30 | 31 | R0.03 (September 22, 2006) 32 | 33 | Added f_rename(). 34 | Changed option _FS_MINIMUM to _FS_MINIMIZE. 35 | 36 | 37 | 38 | R0.03a (December 11, 2006) 39 | 40 | Improved cluster scan algorithm to write files fast. 41 | Fixed f_mkdir() creates incorrect directory on FAT32. 42 | 43 | 44 | 45 | R0.04 (February 04, 2007) 46 | 47 | Added f_mkfs(). 48 | Supported multiple drive system. 49 | Changed some interfaces for multiple drive system. 50 | Changed f_mountdrv() to f_mount(). 51 | 52 | 53 | 54 | R0.04a (April 01, 2007) 55 | 56 | Supported multiple partitions on a physical drive. 57 | Added a capability of extending file size to f_lseek(). 58 | Added minimization level 3. 59 | Fixed an endian sensitive code in f_mkfs(). 60 | 61 | 62 | 63 | R0.04b (May 05, 2007) 64 | 65 | Added a configuration option _USE_NTFLAG. 66 | Added FSINFO support. 67 | Fixed DBCS name can result FR_INVALID_NAME. 68 | Fixed short seek (<= csize) collapses the file object. 69 | 70 | 71 | 72 | R0.05 (August 25, 2007) 73 | 74 | Changed arguments of f_read(), f_write() and f_mkfs(). 75 | Fixed f_mkfs() on FAT32 creates incorrect FSINFO. 76 | Fixed f_mkdir() on FAT32 creates incorrect directory. 77 | 78 | 79 | 80 | R0.05a (February 03, 2008) 81 | 82 | Added f_truncate() and f_utime(). 83 | Fixed off by one error at FAT sub-type determination. 84 | Fixed btr in f_read() can be mistruncated. 85 | Fixed cached sector is not flushed when create and close without write. 86 | 87 | 88 | 89 | R0.06 (April 01, 2008) 90 | 91 | Added fputc(), fputs(), fprintf() and fgets(). 92 | Improved performance of f_lseek() on moving to the same or following cluster. 93 | 94 | 95 | 96 | R0.07 (April 01, 2009) 97 | 98 | Merged Tiny-FatFs as a configuration option. (_FS_TINY) 99 | Added long file name feature. (_USE_LFN) 100 | Added multiple code page feature. (_CODE_PAGE) 101 | Added re-entrancy for multitask operation. (_FS_REENTRANT) 102 | Added auto cluster size selection to f_mkfs(). 103 | Added rewind option to f_readdir(). 104 | Changed result code of critical errors. 105 | Renamed string functions to avoid name collision. 106 | 107 | 108 | 109 | R0.07a (April 14, 2009) 110 | 111 | Septemberarated out OS dependent code on reentrant cfg. 112 | Added multiple sector size feature. 113 | 114 | 115 | 116 | R0.07c (June 21, 2009) 117 | 118 | Fixed f_unlink() can return FR_OK on error. 119 | Fixed wrong cache control in f_lseek(). 120 | Added relative path feature. 121 | Added f_chdir() and f_chdrive(). 122 | Added proper case conversion to extended character. 123 | 124 | 125 | 126 | R0.07e (November 03, 2009) 127 | 128 | Septemberarated out configuration options from ff.h to ffconf.h. 129 | Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH. 130 | Fixed name matching error on the 13 character boundary. 131 | Added a configuration option, _LFN_UNICODE. 132 | Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. 133 | 134 | 135 | 136 | R0.08 (May 15, 2010) 137 | 138 | Added a memory configuration option. (_USE_LFN = 3) 139 | Added file lock feature. (_FS_SHARE) 140 | Added fast seek feature. (_USE_FASTSEEK) 141 | Changed some types on the API, XCHAR->TCHAR. 142 | Changed .fname in the FILINFO structure on Unicode cfg. 143 | String functions support UTF-8 encoding files on Unicode cfg. 144 | 145 | 146 | 147 | R0.08a (August 16, 2010) 148 | 149 | Added f_getcwd(). (_FS_RPATH = 2) 150 | Added sector erase feature. (_USE_ERASE) 151 | Moved file lock semaphore table from fs object to the bss. 152 | Fixed f_mkfs() creates wrong FAT32 volume. 153 | 154 | 155 | 156 | R0.08b (January 15, 2011) 157 | 158 | Fast seek feature is also applied to f_read() and f_write(). 159 | f_lseek() reports required table size on creating CLMP. 160 | Extended format syntax of f_printf(). 161 | Ignores duplicated directory separators in given path name. 162 | 163 | 164 | 165 | R0.09 (September 06, 2011) 166 | 167 | f_mkfs() supports multiple partition to complete the multiple partition feature. 168 | Added f_fdisk(). 169 | 170 | 171 | 172 | R0.09a (August 27, 2012) 173 | 174 | Changed f_open() and f_opendir() reject null object pointer to avoid crash. 175 | Changed option name _FS_SHARE to _FS_LOCK. 176 | Fixed assertion failure due to OS/2 EA on FAT12/16 volume. 177 | 178 | 179 | 180 | R0.09b (January 24, 2013) 181 | 182 | Added f_setlabel() and f_getlabel(). 183 | 184 | 185 | 186 | R0.10 (October 02, 2013) 187 | 188 | Added selection of character encoding on the file. (_STRF_ENCODE) 189 | Added f_closedir(). 190 | Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO) 191 | Added forced mount feature with changes of f_mount(). 192 | Improved behavior of volume auto detection. 193 | Improved write throughput of f_puts() and f_printf(). 194 | Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write(). 195 | Fixed f_write() can be truncated when the file size is close to 4GB. 196 | Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error. 197 | 198 | 199 | 200 | R0.10a (January 15, 2014) 201 | 202 | Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID) 203 | Added a configuration option of minimum sector size. (_MIN_SS) 204 | 2nd argument of f_rename() can have a drive number and it will be ignored. 205 | Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10) 206 | Fixed f_close() invalidates the file object without volume lock. 207 | Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10) 208 | Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07) 209 | 210 | 211 | 212 | R0.10b (May 19, 2014) 213 | 214 | Fixed a hard error in the disk I/O layer can collapse the directory entry. 215 | Fixed LFN entry is not deleted when delete/rename an object with lossy converted SFN. (appeared at R0.07) 216 | 217 | 218 | 219 | R0.10c (November 09, 2014) 220 | 221 | Added a configuration option for the platforms without RTC. (_FS_NORTC) 222 | Changed option name _USE_ERASE to _USE_TRIM. 223 | Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b) 224 | Fixed a potential problem of FAT access that can appear on disk error. 225 | Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08) 226 | 227 | 228 | 229 | R0.11 (February 09, 2015) 230 | 231 | Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND) 232 | Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c) 233 | Fixed _FS_NORTC option does not work properly. (appeared at R0.10c) 234 | 235 | 236 | 237 | R0.11a (September 05, 2015) 238 | 239 | Fixed wrong media change can lead a deadlock at thread-safe configuration. 240 | Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE) 241 | Removed some code pages actually not exist on the standard systems. (_CODE_PAGE) 242 | Fixed errors in the case conversion teble of code page 437 and 850 (ff.c). 243 | Fixed errors in the case conversion teble of Unicode (cc*.c). 244 | 245 | 246 | 247 | R0.12 (April 12, 2016) 248 | 249 | Added support for exFAT file system. (_FS_EXFAT) 250 | Added f_expand(). (_USE_EXPAND) 251 | Changed some members in FINFO structure and behavior of f_readdir(). 252 | Added an option _USE_CHMOD. 253 | Removed an option _WORD_ACCESS. 254 | Fixed errors in the case conversion table of Unicode (cc*.c). 255 | 256 | 257 | 258 | R0.12a (July 10, 2016) 259 | 260 | Added support for creating exFAT volume with some changes of f_mkfs(). 261 | Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed. 262 | f_forward() is available regardless of _FS_TINY. 263 | Fixed f_mkfs() creates wrong volume. (appeared at R0.12) 264 | Fixed wrong memory read in create_name(). (appeared at R0.12) 265 | Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD. 266 | 267 | 268 | 269 | R0.12b (September 04, 2016) 270 | 271 | Made f_rename() be able to rename objects with the same name but case. 272 | Fixed an error in the case conversion teble of code page 866. (ff.c) 273 | Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12) 274 | Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12) 275 | Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12) 276 | Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12) 277 | Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12) 278 | Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12) 279 | 280 | 281 | 282 | R0.12c (March 04, 2017) 283 | 284 | Improved write throughput at the fragmented file on the exFAT volume. 285 | Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN. 286 | Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12) 287 | Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c) 288 | 289 | 290 | 291 | R0.13 (May 21, 2017) 292 | 293 | Changed heading character of configuration keywords "_" to "FF_". 294 | Removed ASCII-only configuration, FF_CODE_PAGE = 1. Use FF_CODE_PAGE = 437 instead. 295 | Added f_setcp(), run-time code page configuration. (FF_CODE_PAGE = 0) 296 | Improved cluster allocation time on stretch a deep buried cluster chain. 297 | Improved processing time of f_mkdir() with large cluster size by using FF_USE_LFN = 3. 298 | Improved NoFatChain flag of the fragmented file to be set after it is truncated and got contiguous. 299 | Fixed archive attribute is left not set when a file on the exFAT volume is renamed. (appeared at R0.12) 300 | Fixed exFAT FAT entry can be collapsed when write or lseek operation to the existing file is done. (appeared at R0.12c) 301 | Fixed creating a file can fail when a new cluster allocation to the exFAT directory occures. (appeared at R0.12c) 302 | 303 | -------------------------------------------------------------------------------- /fatfs/ffconf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs - Configuration file 3 | /---------------------------------------------------------------------------*/ 4 | 5 | #define FFCONF_DEF 87030 /* Revision ID */ 6 | 7 | /*---------------------------------------------------------------------------/ 8 | / Function Configurations 9 | /---------------------------------------------------------------------------*/ 10 | 11 | #define FF_FS_READONLY 1 12 | /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) 13 | / Read-only configuration removes writing API functions, f_write(), f_sync(), 14 | / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() 15 | / and optional writing functions as well. */ 16 | 17 | 18 | #define FF_FS_MINIMIZE 1 19 | /* This option defines minimization level to remove some basic API functions. 20 | / 21 | / 0: All basic functions are enabled. 22 | / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() 23 | / are removed. 24 | / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. 25 | / 3: f_lseek() function is removed in addition to 2. */ 26 | 27 | 28 | #define FF_USE_STRFUNC 0 29 | /* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). 30 | / 31 | / 0: Disable string functions. 32 | / 1: Enable without LF-CRLF conversion. 33 | / 2: Enable with LF-CRLF conversion. */ 34 | 35 | 36 | #define FF_USE_FIND 0 37 | /* This option switches filtered directory read functions, f_findfirst() and 38 | / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ 39 | 40 | 41 | #define FF_USE_MKFS 0 42 | /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ 43 | 44 | 45 | #define FF_USE_FASTSEEK 0 46 | /* This option switches fast seek function. (0:Disable or 1:Enable) */ 47 | 48 | 49 | #define FF_USE_EXPAND 0 50 | /* This option switches f_expand function. (0:Disable or 1:Enable) */ 51 | 52 | 53 | #define FF_USE_CHMOD 0 54 | /* This option switches attribute manipulation functions, f_chmod() and f_utime(). 55 | / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ 56 | 57 | 58 | #define FF_USE_LABEL 0 59 | /* This option switches volume label functions, f_getlabel() and f_setlabel(). 60 | / (0:Disable or 1:Enable) */ 61 | 62 | 63 | #define FF_USE_FORWARD 0 64 | /* This option switches f_forward() function. (0:Disable or 1:Enable) */ 65 | 66 | 67 | /*---------------------------------------------------------------------------/ 68 | / Locale and Namespace Configurations 69 | /---------------------------------------------------------------------------*/ 70 | 71 | #define FF_CODE_PAGE 437 72 | /* This option specifies the OEM code page to be used on the target system. 73 | / Incorrect code page setting can cause a file open failure. 74 | / 75 | / 437 - U.S. 76 | / 720 - Arabic 77 | / 737 - Greek 78 | / 771 - KBL 79 | / 775 - Baltic 80 | / 850 - Latin 1 81 | / 852 - Latin 2 82 | / 855 - Cyrillic 83 | / 857 - Turkish 84 | / 860 - Portuguese 85 | / 861 - Icelandic 86 | / 862 - Hebrew 87 | / 863 - Canadian French 88 | / 864 - Arabic 89 | / 865 - Nordic 90 | / 866 - Russian 91 | / 869 - Greek 2 92 | / 932 - Japanese (DBCS) 93 | / 936 - Simplified Chinese (DBCS) 94 | / 949 - Korean (DBCS) 95 | / 950 - Traditional Chinese (DBCS) 96 | / 0 - Include all code pages above and configured by f_setcp() 97 | */ 98 | 99 | 100 | #define FF_USE_LFN 0 101 | #define FF_MAX_LFN 255 102 | /* The FF_USE_LFN switches the support for LFN (long file name). 103 | / 104 | / 0: Disable LFN. FF_MAX_LFN has no effect. 105 | / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. 106 | / 2: Enable LFN with dynamic working buffer on the STACK. 107 | / 3: Enable LFN with dynamic working buffer on the HEAP. 108 | / 109 | / To enable the LFN, Unicode handling functions (option/unicode.c) must be added 110 | / to the project. The working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and 111 | / additional 608 bytes at exFAT enabled. FF_MAX_LFN can be in range from 12 to 255. 112 | / It should be set 255 to support full featured LFN operations. 113 | / When use stack for the working buffer, take care on stack overflow. When use heap 114 | / memory for the working buffer, memory management functions, ff_memalloc() and 115 | / ff_memfree(), must be added to the project. */ 116 | 117 | 118 | #define FF_LFN_UNICODE 0 119 | /* This option switches character encoding on the API, 0:ANSI/OEM or 1:UTF-16, 120 | / when LFN is enabled. Also behavior of string I/O functions will be affected by 121 | / this option. When LFN is not enabled, this option has no effect. 122 | */ 123 | 124 | 125 | #define FF_STRF_ENCODE 3 126 | /* When FF_LFN_UNICODE = 1 with LFN enabled, string I/O functions, f_gets(), 127 | / f_putc(), f_puts and f_printf() convert the character encoding in it. 128 | / This option selects assumption of character encoding ON THE FILE to be 129 | / read/written via those functions. 130 | / 131 | / 0: ANSI/OEM 132 | / 1: UTF-16LE 133 | / 2: UTF-16BE 134 | / 3: UTF-8 135 | */ 136 | 137 | 138 | #define FF_FS_RPATH 0 139 | /* This option configures support for relative path. 140 | / 141 | / 0: Disable relative path and remove related functions. 142 | / 1: Enable relative path. f_chdir() and f_chdrive() are available. 143 | / 2: f_getcwd() function is available in addition to 1. 144 | */ 145 | 146 | 147 | /*---------------------------------------------------------------------------/ 148 | / Drive/Volume Configurations 149 | /---------------------------------------------------------------------------*/ 150 | 151 | #define FF_VOLUMES 4 152 | /* Number of volumes (logical drives) to be used. (1-10) */ 153 | 154 | 155 | #define FF_STR_VOLUME_ID 0 156 | #define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" 157 | /* FF_STR_VOLUME_ID switches string support for volume ID. 158 | / When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive 159 | / number in the path name. FF_VOLUME_STRS defines the drive ID strings for each 160 | / logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for 161 | / the drive ID strings are: A-Z and 0-9. */ 162 | 163 | 164 | #define FF_MULTI_PARTITION 1 165 | /* This option switches support for multiple volumes on the physical drive. 166 | / By default (0), each logical drive number is bound to the same physical drive 167 | / number and only an FAT volume found on the physical drive will be mounted. 168 | / When this function is enabled (1), each logical drive number can be bound to 169 | / arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() 170 | / function will be available. */ 171 | 172 | 173 | #define FF_MIN_SS 512 174 | #define FF_MAX_SS 512 175 | /* This set of options configures the range of sector size to be supported. (512, 176 | / 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and 177 | / harddisk. But a larger value may be required for on-board flash memory and some 178 | / type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured 179 | / for variable sector size mode and disk_ioctl() function needs to implement 180 | / GET_SECTOR_SIZE command. */ 181 | 182 | 183 | #define FF_USE_TRIM 0 184 | /* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) 185 | / To enable Trim function, also CTRL_TRIM command should be implemented to the 186 | / disk_ioctl() function. */ 187 | 188 | 189 | #define FF_FS_NOFSINFO 0 190 | /* If you need to know correct free space on the FAT32 volume, set bit 0 of this 191 | / option, and f_getfree() function at first time after volume mount will force 192 | / a full FAT scan. Bit 1 controls the use of last allocated cluster number. 193 | / 194 | / bit0=0: Use free cluster count in the FSINFO if available. 195 | / bit0=1: Do not trust free cluster count in the FSINFO. 196 | / bit1=0: Use last allocated cluster number in the FSINFO if available. 197 | / bit1=1: Do not trust last allocated cluster number in the FSINFO. 198 | */ 199 | 200 | 201 | 202 | /*---------------------------------------------------------------------------/ 203 | / System Configurations 204 | /---------------------------------------------------------------------------*/ 205 | 206 | #define FF_FS_TINY 0 207 | /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) 208 | / At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. 209 | / Instead of private sector buffer eliminated from the file object, common sector 210 | / buffer in the filesystem object (FATFS) is used for the file data transfer. */ 211 | 212 | 213 | #define FF_FS_EXFAT 0 214 | /* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) 215 | / When enable exFAT, also LFN needs to be enabled. 216 | / Note that enabling exFAT discards ANSI C (C89) compatibility. */ 217 | 218 | 219 | #define FF_FS_NORTC 0 220 | #define FF_NORTC_MON 5 221 | #define FF_NORTC_MDAY 1 222 | #define FF_NORTC_YEAR 2017 223 | /* The option FF_FS_NORTC switches timestamp functiton. If the system does not have 224 | / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable 225 | / the timestamp function. All objects modified by FatFs will have a fixed timestamp 226 | / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. 227 | / To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be 228 | / added to the project to read current time form real-time clock. FF_NORTC_MON, 229 | / FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. 230 | / These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ 231 | 232 | 233 | #define FF_FS_LOCK 0 234 | /* The option FF_FS_LOCK switches file lock function to control duplicated file open 235 | / and illegal operation to open objects. This option must be 0 when FF_FS_READONLY 236 | / is 1. 237 | / 238 | / 0: Disable file lock function. To avoid volume corruption, application program 239 | / should avoid illegal open, remove and rename to the open objects. 240 | / >0: Enable file lock function. The value defines how many files/sub-directories 241 | / can be opened simultaneously under file lock control. Note that the file 242 | / lock control is independent of re-entrancy. */ 243 | 244 | 245 | #define FF_FS_REENTRANT 0 246 | #define FF_FS_TIMEOUT 1000 247 | #define FF_SYNC_t HANDLE 248 | /* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs 249 | / module itself. Note that regardless of this option, file access to different 250 | / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() 251 | / and f_fdisk() function, are always not re-entrant. Only file/directory access 252 | / to the same volume is under control of this function. 253 | / 254 | / 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. 255 | / 1: Enable re-entrancy. Also user provided synchronization handlers, 256 | / ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() 257 | / function, must be added to the project. Samples are available in 258 | / option/syscall.c. 259 | / 260 | / The FF_FS_TIMEOUT defines timeout period in unit of time tick. 261 | / The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, 262 | / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be 263 | / included somewhere in the scope of ff.h. */ 264 | 265 | /* #include // O/S definitions */ 266 | 267 | 268 | 269 | /*--- End of configuration options ---*/ 270 | -------------------------------------------------------------------------------- /video_low.c: -------------------------------------------------------------------------------- 1 | /* 2 | BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader. 3 | low-level video support for the BootMii UI 4 | 5 | Copyright (C) 2008, 2009 Hector Martin "marcan" 6 | Copyright (C) 2009 Haxx Enterprises 7 | Copyright (c) 2009 Sven Peter 8 | 9 | # This code is licensed to you under the terms of the GNU GPL, version 2; 10 | # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 11 | 12 | Some routines and initialization constants originally came from the 13 | "GAMECUBE LOW LEVEL INFO" document and sourcecode released by Titanik 14 | of Crazy Nation and the GC Linux project. 15 | */ 16 | 17 | #include "powerpc.h" 18 | #include "video_low.h" 19 | #include "string.h" 20 | 21 | #ifdef VI_DEBUG 22 | #define VI_debug(f, arg...) printf("VI: " f, ##arg); 23 | #else 24 | #define VI_debug(f, arg...) while(0) 25 | #endif 26 | 27 | // hardcoded VI init states 28 | static const u16 VIDEO_Mode640X480NtsciYUV16[64] = { 29 | 0x0F06, 0x0001, 0x4769, 0x01AD, 0x02EA, 0x5140, 0x0003, 0x0018, 30 | 0x0002, 0x0019, 0x410C, 0x410C, 0x40ED, 0x40ED, 0x0043, 0x5A4E, 31 | 0x0000, 0x0000, 0x0043, 0x5A4E, 0x0000, 0x0000, 0x0000, 0x0000, 32 | 0x1107, 0x01AE, 0x1001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 33 | 0x0000, 0x0000, 0x0000, 0x0000, 0x2850, 0x0100, 0x1AE7, 0x71F0, 34 | 0x0DB4, 0xA574, 0x00C1, 0x188E, 0xC4C0, 0xCBE2, 0xFCEC, 0xDECF, 35 | 0x1313, 0x0F08, 0x0008, 0x0C0F, 0x00FF, 0x0000, 0x0000, 0x0000, 36 | 0x0280, 0x0000, 0x0000, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF}; 37 | 38 | static const u16 VIDEO_Mode640X480Pal50YUV16[64] = { 39 | 0x11F5, 0x0101, 0x4B6A, 0x01B0, 0x02F8, 0x5640, 0x0001, 0x0023, 40 | 0x0000, 0x0024, 0x4D2B, 0x4D6D, 0x4D8A, 0x4D4C, 0x0043, 0x5A4E, 41 | 0x0000, 0x0000, 0x0043, 0x5A4E, 0x0000, 0x0000, 0x013C, 0x0144, 42 | 0x1139, 0x01B1, 0x1001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 43 | 0x0000, 0x0000, 0x0000, 0x0000, 0x2850, 0x0100, 0x1AE7, 0x71F0, 44 | 0x0DB4, 0xA574, 0x00C1, 0x188E, 0xC4C0, 0xCBE2, 0xFCEC, 0xDECF, 45 | 0x1313, 0x0F08, 0x0008, 0x0C0F, 0x00FF, 0x0000, 0x0000, 0x0000, 46 | 0x0280, 0x0000, 0x0000, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF}; 47 | 48 | static const u16 VIDEO_Mode640X480Pal60YUV16[64] = { 49 | 0x0F06, 0x0001, 0x4769, 0x01AD, 0x02EA, 0x5140, 0x0003, 0x0018, 50 | 0x0002, 0x0019, 0x410C, 0x410C, 0x40ED, 0x40ED, 0x0043, 0x5A4E, 51 | 0x0000, 0x0000, 0x0043, 0x5A4E, 0x0000, 0x0000, 0x0005, 0x0176, 52 | 0x1107, 0x01AE, 0x1001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 53 | 0x0000, 0x0000, 0x0000, 0x0000, 0x2850, 0x0100, 0x1AE7, 0x71F0, 54 | 0x0DB4, 0xA574, 0x00C1, 0x188E, 0xC4C0, 0xCBE2, 0xFCEC, 0xDECF, 55 | 0x1313, 0x0F08, 0x0008, 0x0C0F, 0x00FF, 0x0000, 0x0000, 0x0000, 56 | 0x0280, 0x0000, 0x0000, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF}; 57 | 58 | static const u16 VIDEO_Mode640X480NtscpYUV16[64] = { 59 | 0x1E0C, 0x0005, 0x4769, 0x01AD, 0x02EA, 0x5140, 0x0006, 0x0030, 60 | 0x0006, 0x0030, 0x81D8, 0x81D8, 0x81D8, 0x81D8, 0x0015, 0x77A0, 61 | 0x0000, 0x0000, 0x0015, 0x77A0, 0x0000, 0x0000, 0x022A, 0x01D6, 62 | 0x120E, 0x0001, 0x1001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 63 | 0x0000, 0x0000, 0x0000, 0x0000, 0x2828, 0x0100, 0x1AE7, 0x71F0, 64 | 0x0DB4, 0xA574, 0x00C1, 0x188E, 0xC4C0, 0xCBE2, 0xFCEC, 0xDECF, 65 | 0x1313, 0x0F08, 0x0008, 0x0C0F, 0x00FF, 0x0000, 0x0001, 0x0001, 66 | 0x0280, 0x807A, 0x019C, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF}; 67 | 68 | static int video_mode; 69 | 70 | void VIDEO_Init(int VideoMode) 71 | { 72 | u32 Counter=0; 73 | const u16 *video_initstate=NULL; 74 | 75 | VI_debug("Resetting VI...\n"); 76 | write16(R_VIDEO_STATUS1, 2); 77 | usleep(2); 78 | write16(R_VIDEO_STATUS1, 0); 79 | VI_debug("VI reset...\n"); 80 | 81 | switch(VideoMode) 82 | { 83 | case VIDEO_640X480_NTSCi_YUV16: 84 | video_initstate = VIDEO_Mode640X480NtsciYUV16; 85 | break; 86 | 87 | case VIDEO_640X480_PAL50_YUV16: 88 | video_initstate = VIDEO_Mode640X480Pal50YUV16; 89 | break; 90 | 91 | case VIDEO_640X480_PAL60_YUV16: 92 | video_initstate = VIDEO_Mode640X480Pal60YUV16; 93 | break; 94 | 95 | case VIDEO_640X480_NTSCp_YUV16: 96 | video_initstate = VIDEO_Mode640X480NtscpYUV16; 97 | break; 98 | 99 | /* Use NTSC as default */ 100 | default: 101 | VideoMode = VIDEO_640X480_NTSCi_YUV16; 102 | video_initstate = VIDEO_Mode640X480NtsciYUV16; 103 | break; 104 | } 105 | 106 | VI_debug("Configuring VI...\n"); 107 | for(Counter=0; Counter<64; Counter++) 108 | { 109 | if(Counter==1) 110 | write16(MEM_VIDEO_BASE + 2*Counter, video_initstate[Counter] & 0xFFFE); 111 | else 112 | write16(MEM_VIDEO_BASE + 2*Counter, video_initstate[Counter]); 113 | } 114 | 115 | video_mode = VideoMode; 116 | 117 | write16(R_VIDEO_STATUS1, video_initstate[1]); 118 | #ifdef VI_DEBUG 119 | VI_debug("VI dump:\n"); 120 | for(Counter=0; Counter<32; Counter++) 121 | printf("%02x: %04x %04x,\n", Counter*4, read16(MEM_VIDEO_BASE + Counter*4), read16(MEM_VIDEO_BASE + Counter*4+2)); 122 | 123 | printf("---\n"); 124 | #endif 125 | } 126 | 127 | void VIDEO_SetFrameBuffer(void *FrameBufferAddr) 128 | { 129 | u32 fb = virt_to_phys(FrameBufferAddr); 130 | 131 | write32(R_VIDEO_FRAMEBUFFER_1, (fb >> 5) | 0x10000000); 132 | if(video_mode != VIDEO_640X480_NTSCp_YUV16) 133 | fb += 2 * 640; // 640 pixels == 1 line 134 | write32(R_VIDEO_FRAMEBUFFER_2, (fb >> 5) | 0x10000000); 135 | } 136 | 137 | void VIDEO_WaitVSync(void) 138 | { 139 | while(read16(R_VIDEO_HALFLINE_1) >= 200); 140 | while(read16(R_VIDEO_HALFLINE_1) < 200); 141 | } 142 | 143 | /* black out video (not reversible!) */ 144 | void VIDEO_BlackOut(void) 145 | { 146 | VIDEO_WaitVSync(); 147 | 148 | int active = read32(R_VIDEO_VTIMING) >> 4; 149 | 150 | write32(R_VIDEO_PRB_ODD, read32(R_VIDEO_PRB_ODD) + ((active<<1)-2)); 151 | write32(R_VIDEO_PRB_EVEN, read32(R_VIDEO_PRB_EVEN) + ((active<<1)-2)); 152 | write32(R_VIDEO_PSB_ODD, read32(R_VIDEO_PSB_ODD) + 2); 153 | write32(R_VIDEO_PSB_EVEN, read32(R_VIDEO_PSB_EVEN) + 2); 154 | 155 | mask32(R_VIDEO_VTIMING, 0xfffffff0, 0); 156 | } 157 | 158 | //static vu16* const _viReg = (u16*)0xCC002000; 159 | 160 | void VIDEO_Shutdown(void) 161 | { 162 | VIDEO_BlackOut(); 163 | write16(R_VIDEO_STATUS1, 0); 164 | } 165 | 166 | #define SLAVE_AVE 0xe0 167 | 168 | static inline void aveSetDirection(u32 dir) 169 | { 170 | u32 val = (read32(HW_GPIO1BDIR)&~0x8000)|0x4000; 171 | if(dir) val |= 0x8000; 172 | write32(HW_GPIO1BDIR, val); 173 | } 174 | 175 | static inline void aveSetSCL(u32 scl) 176 | { 177 | u32 val = read32(HW_GPIO1BOUT)&~0x4000; 178 | if(scl) val |= 0x4000; 179 | write32(HW_GPIO1BOUT, val); 180 | } 181 | 182 | static inline void aveSetSDA(u32 sda) 183 | { 184 | u32 val = read32(HW_GPIO1BOUT)&~0x8000; 185 | if(sda) val |= 0x8000; 186 | write32(HW_GPIO1BOUT, val); 187 | } 188 | 189 | static inline u32 aveGetSDA() 190 | { 191 | if(read32(HW_GPIO1BIN)&0x8000) 192 | return 1; 193 | else 194 | return 0; 195 | } 196 | 197 | static u32 __sendSlaveAddress(u8 addr) 198 | { 199 | u32 i; 200 | 201 | aveSetSDA(0); 202 | usleep(2); 203 | 204 | aveSetSCL(0); 205 | for(i=0;i<8;i++) { 206 | if(addr&0x80) aveSetSDA(1); 207 | else aveSetSDA(0); 208 | usleep(2); 209 | 210 | aveSetSCL(1); 211 | usleep(2); 212 | 213 | aveSetSCL(0); 214 | addr <<= 1; 215 | } 216 | 217 | aveSetDirection(0); 218 | usleep(2); 219 | 220 | aveSetSCL(1); 221 | usleep(2); 222 | 223 | if(aveGetSDA()!=0) { 224 | VI_debug("No ACK\n"); 225 | return 0; 226 | } 227 | 228 | aveSetSDA(0); 229 | aveSetDirection(1); 230 | aveSetSCL(0); 231 | 232 | return 1; 233 | } 234 | 235 | static u32 __VISendI2CData(u8 addr,void *val,u32 len) 236 | { 237 | u8 c; 238 | u32 i,j; 239 | u32 ret; 240 | 241 | VI_debug("I2C[%02x]:",addr); 242 | for(i=0;i> 8; 308 | buf[2] = data & 0xFF; 309 | __VISendI2CData(SLAVE_AVE,buf,3); 310 | usleep(2); 311 | } 312 | 313 | static void __VIWriteI2CRegister32(u8 reg, u32 data) 314 | { 315 | u8 buf[5]; 316 | buf[0] = reg; 317 | buf[1] = data >> 24; 318 | buf[2] = (data >> 16) & 0xFF; 319 | buf[3] = (data >> 8) & 0xFF; 320 | buf[4] = data & 0xFF; 321 | __VISendI2CData(SLAVE_AVE,buf,5); 322 | usleep(2); 323 | } 324 | 325 | static void __VIWriteI2CRegisterBuf(u8 reg, int size, u8 *data) 326 | { 327 | u8 buf[0x100]; 328 | buf[0] = reg; 329 | memcpy(&buf[1], data, size); 330 | __VISendI2CData(SLAVE_AVE,buf,size+1); 331 | usleep(2); 332 | } 333 | 334 | static void __VISetYUVSEL(u8 dtvstatus) 335 | { 336 | int vdacFlagRegion; 337 | switch(video_mode) { 338 | case VIDEO_640X480_NTSCi_YUV16: 339 | case VIDEO_640X480_NTSCp_YUV16: 340 | default: 341 | vdacFlagRegion = 0; 342 | break; 343 | case VIDEO_640X480_PAL50_YUV16: 344 | case VIDEO_640X480_PAL60_YUV16: 345 | vdacFlagRegion = 2; 346 | break; 347 | } 348 | __VIWriteI2CRegister8(0x01, (dtvstatus<<5) | (vdacFlagRegion&0x1f)); 349 | } 350 | 351 | static void __VISetFilterEURGB60(u8 enable) 352 | { 353 | __VIWriteI2CRegister8(0x6e, enable); 354 | } 355 | 356 | void VISetupEncoder(void) 357 | { 358 | u8 macrobuf[0x1a]; 359 | 360 | u8 gamma[0x21] = { 361 | 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 362 | 0x10, 0x00, 0x10, 0x00, 0x10, 0x20, 0x40, 0x60, 363 | 0x80, 0xa0, 0xeb, 0x10, 0x00, 0x20, 0x00, 0x40, 364 | 0x00, 0x60, 0x00, 0x80, 0x00, 0xa0, 0x00, 0xeb, 365 | 0x00 366 | }; 367 | 368 | u8 dtv; 369 | 370 | //tv = VIDEO_GetCurrentTvMode(); 371 | dtv = read16(R_VIDEO_VISEL) & 1; 372 | //oldDtvStatus = dtv; 373 | 374 | // SetRevolutionModeSimple 375 | 376 | VI_debug("DTV status: %d\n", dtv); 377 | 378 | memset(macrobuf, 0, 0x1a); 379 | 380 | __VIWriteI2CRegister8(0x6a, 1); 381 | __VIWriteI2CRegister8(0x65, 1); 382 | __VISetYUVSEL(dtv); 383 | __VIWriteI2CRegister8(0x00, 0); 384 | __VIWriteI2CRegister16(0x71, 0x8e8e); 385 | __VIWriteI2CRegister8(0x02, 7); 386 | __VIWriteI2CRegister16(0x05, 0x0000); 387 | __VIWriteI2CRegister16(0x08, 0x0000); 388 | __VIWriteI2CRegister32(0x7A, 0x00000000); 389 | 390 | // Macrovision crap 391 | __VIWriteI2CRegisterBuf(0x40, sizeof(macrobuf), macrobuf); 392 | 393 | // Sometimes 1 in RGB mode? (reg 1 == 3) 394 | __VIWriteI2CRegister8(0x0A, 0); 395 | 396 | __VIWriteI2CRegister8(0x03, 1); 397 | 398 | __VIWriteI2CRegisterBuf(0x10, sizeof(gamma), gamma); 399 | 400 | __VIWriteI2CRegister8(0x04, 1); 401 | __VIWriteI2CRegister32(0x7A, 0x00000000); 402 | __VIWriteI2CRegister16(0x08, 0x0000); 403 | __VIWriteI2CRegister8(0x03, 1); 404 | 405 | //if(tv==VI_EURGB60) __VISetFilterEURGB60(1); 406 | //else 407 | __VISetFilterEURGB60(0); 408 | 409 | //oldTvStatus = tv; 410 | } 411 | 412 | -------------------------------------------------------------------------------- /fatfs/ff.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------/ 2 | / FatFs - Generic FAT Filesystem module R0.13 / 3 | /-----------------------------------------------------------------------------/ 4 | / 5 | / Copyright (C) 2017, ChaN, all right reserved. 6 | / 7 | / FatFs module is an open source software. Redistribution and use of FatFs in 8 | / source and binary forms, with or without modification, are permitted provided 9 | / that the following condition is met: 10 | 11 | / 1. Redistributions of source code must retain the above copyright notice, 12 | / this condition and the following disclaimer. 13 | / 14 | / This software is provided by the copyright holder and contributors "AS IS" 15 | / and any warranties related to this software are DISCLAIMED. 16 | / The copyright owner or contributors be NOT LIABLE for any damages caused 17 | / by use of this software. 18 | / 19 | /----------------------------------------------------------------------------*/ 20 | 21 | 22 | #ifndef FF_DEFINED 23 | #define FF_DEFINED 87030 /* Revision ID */ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | #include "integer.h" /* Basic integer types */ 30 | #include "ffconf.h" /* FatFs configuration options */ 31 | 32 | #if FF_DEFINED != FFCONF_DEF 33 | #error Wrong configuration file (ffconf.h). 34 | #endif 35 | 36 | 37 | 38 | /* Definitions of volume management */ 39 | 40 | #if FF_MULTI_PARTITION /* Multiple partition configuration */ 41 | typedef struct { 42 | BYTE pd; /* Physical drive number */ 43 | BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ 44 | } PARTITION; 45 | extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ 46 | #endif 47 | 48 | 49 | 50 | /* Type of path name strings on FatFs API */ 51 | 52 | #if FF_LFN_UNICODE && FF_USE_LFN /* Unicode (UTF-16) string */ 53 | #ifndef _INC_TCHAR 54 | typedef WCHAR TCHAR; 55 | #define _T(x) L ## x 56 | #define _TEXT(x) L ## x 57 | #define _INC_TCHAR 58 | #endif 59 | #else /* ANSI/OEM string */ 60 | #ifndef _INC_TCHAR 61 | typedef char TCHAR; 62 | #define _T(x) x 63 | #define _TEXT(x) x 64 | #define _INC_TCHAR 65 | #endif 66 | #endif 67 | 68 | 69 | 70 | /* Type of file size variables */ 71 | 72 | #if FF_FS_EXFAT 73 | #if !FF_USE_LFN 74 | #error LFN must be enabled when enable exFAT 75 | #endif 76 | typedef QWORD FSIZE_t; 77 | #else 78 | typedef DWORD FSIZE_t; 79 | #endif 80 | 81 | 82 | 83 | /* Filesystem object structure (FATFS) */ 84 | 85 | typedef struct { 86 | BYTE fs_type; /* Filesystem type (0:N/A) */ 87 | BYTE pdrv; /* Physical drive number */ 88 | BYTE n_fats; /* Number of FATs (1 or 2) */ 89 | BYTE wflag; /* win[] flag (b0:dirty) */ 90 | BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ 91 | WORD id; /* Volume mount ID */ 92 | WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ 93 | WORD csize; /* Cluster size [sectors] */ 94 | #if FF_MAX_SS != FF_MIN_SS 95 | WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ 96 | #endif 97 | #if FF_USE_LFN 98 | WCHAR* lfnbuf; /* LFN working buffer */ 99 | #endif 100 | #if FF_FS_EXFAT 101 | BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ 102 | #endif 103 | #if FF_FS_REENTRANT 104 | FF_SYNC_t sobj; /* Identifier of sync object */ 105 | #endif 106 | #if !FF_FS_READONLY 107 | DWORD last_clst; /* Last allocated cluster */ 108 | DWORD free_clst; /* Number of free clusters */ 109 | #endif 110 | #if FF_FS_RPATH 111 | DWORD cdir; /* Current directory start cluster (0:root) */ 112 | #if FF_FS_EXFAT 113 | DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ 114 | DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ 115 | DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ 116 | #endif 117 | #endif 118 | DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ 119 | DWORD fsize; /* Size of an FAT [sectors] */ 120 | DWORD volbase; /* Volume base sector */ 121 | DWORD fatbase; /* FAT base sector */ 122 | DWORD dirbase; /* Root directory base sector/cluster */ 123 | DWORD database; /* Data base sector */ 124 | DWORD winsect; /* Current sector appearing in the win[] */ 125 | BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ 126 | } FATFS; 127 | 128 | 129 | 130 | /* Object ID and allocation information (FFOBJID) */ 131 | 132 | typedef struct { 133 | FATFS* fs; /* Pointer to the hosting volume of this object */ 134 | WORD id; /* Hosting volume mount ID */ 135 | BYTE attr; /* Object attribute */ 136 | BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */ 137 | DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ 138 | FSIZE_t objsize; /* Object size (valid when sclust != 0) */ 139 | #if FF_FS_EXFAT 140 | DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ 141 | DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ 142 | DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ 143 | DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ 144 | DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ 145 | #endif 146 | #if FF_FS_LOCK 147 | UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ 148 | #endif 149 | } FFOBJID; 150 | 151 | 152 | 153 | /* File object structure (FIL) */ 154 | 155 | typedef struct { 156 | FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ 157 | BYTE flag; /* File status flags */ 158 | BYTE err; /* Abort flag (error code) */ 159 | FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ 160 | DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ 161 | DWORD sect; /* Sector number appearing in buf[] (0:invalid) */ 162 | #if !FF_FS_READONLY 163 | DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ 164 | BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ 165 | #endif 166 | #if FF_USE_FASTSEEK 167 | DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ 168 | #endif 169 | #if !FF_FS_TINY 170 | BYTE buf[FF_MAX_SS]; /* File private data read/write window */ 171 | #endif 172 | } FIL; 173 | 174 | 175 | 176 | /* Directory object structure (DIR) */ 177 | 178 | typedef struct { 179 | FFOBJID obj; /* Object identifier */ 180 | DWORD dptr; /* Current read/write offset */ 181 | DWORD clust; /* Current cluster */ 182 | DWORD sect; /* Current sector (0:Read operation has terminated) */ 183 | BYTE* dir; /* Pointer to the directory item in the win[] */ 184 | BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ 185 | #if FF_USE_LFN 186 | DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ 187 | #endif 188 | #if FF_USE_FIND 189 | const TCHAR* pat; /* Pointer to the name matching pattern */ 190 | #endif 191 | } DIR; 192 | 193 | 194 | 195 | /* File information structure (FILINFO) */ 196 | 197 | typedef struct { 198 | FSIZE_t fsize; /* File size */ 199 | WORD fdate; /* Modified date */ 200 | WORD ftime; /* Modified time */ 201 | BYTE fattrib; /* File attribute */ 202 | #if FF_USE_LFN 203 | TCHAR altname[13]; /* Altenative file name */ 204 | TCHAR fname[FF_MAX_LFN + 1]; /* Primary file name */ 205 | #else 206 | TCHAR fname[13]; /* File name */ 207 | #endif 208 | } FILINFO; 209 | 210 | 211 | 212 | /* File function return code (FRESULT) */ 213 | 214 | typedef enum { 215 | FR_OK = 0, /* (0) Succeeded */ 216 | FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ 217 | FR_NOT_READY, /* (2) The physical drive cannot work */ 218 | FR_NO_FILE, /* (3) Could not find the file */ 219 | FR_NO_PATH, /* (4) Could not find the path */ 220 | FR_INVALID_NAME, /* (5) The path name format is invalid */ 221 | FR_DENIED, /* (6) Access denied due to prohibited access or directory full */ 222 | FR_EXIST, /* (7) Access denied due to prohibited access */ 223 | FR_INVALID_OBJECT, /* (8) The file/directory object is invalid */ 224 | FR_WRITE_PROTECTED, /* (9) The physical drive is write protected */ 225 | FR_INVALID_DRIVE, /* (10) The logical drive number is invalid */ 226 | FR_NOT_ENABLED, /* (11) The volume has no work area */ 227 | FR_NO_FILESYSTEM, /* (12) There is no valid FAT volume */ 228 | FR_MKFS_ABORTED, /* (13) The f_mkfs() aborted due to any problem */ 229 | FR_TIMEOUT, /* (14) Could not get a grant to access the volume within defined period */ 230 | FR_LOCKED, /* (15) The operation is rejected according to the file sharing policy */ 231 | FR_NOT_ENOUGH_CORE, /* (16) LFN working buffer could not be allocated */ 232 | FR_TOO_MANY_OPEN_FILES, /* (17) Number of open files > FF_FS_LOCK */ 233 | FR_INVALID_PARAMETER, /* (18) Given parameter is invalid */ 234 | FR_INT_ERR, /* (19) Assertion failed */ 235 | FR_CLS_INT_ERR, /* (20) */ 236 | FR_DIR1_ERR, /* (21) */ 237 | FR_DIR2_ERR, /* (22) */ 238 | FR_DIR3_ERR, /* (23) */ 239 | FR_DIR4_ERR, /* (24) */ 240 | FR_DIR5_ERR, /* (25) */ 241 | FR_DIR6_ERR, /* (26) */ 242 | FR_DIR7_ERR, /* (27) */ 243 | FR_DIR8_ERR, /* (28) */ 244 | FR_DIR9_ERR, /* (29) */ 245 | FR_DIR10_ERR, /* (30) */ 246 | FR_DIR11_ERR, /* (31) */ 247 | FR_DIR12_ERR /* (32) */ 248 | } FRESULT; 249 | 250 | 251 | 252 | /*--------------------------------------------------------------*/ 253 | /* FatFs module application interface */ 254 | 255 | FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ 256 | FRESULT f_close (FIL* fp); /* Close an open file object */ 257 | FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ 258 | FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ 259 | FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ 260 | FRESULT f_truncate (FIL* fp); /* Truncate the file */ 261 | FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ 262 | FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ 263 | FRESULT f_closedir (DIR* dp); /* Close an open directory */ 264 | FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ 265 | FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ 266 | FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ 267 | FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ 268 | FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ 269 | FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ 270 | FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ 271 | FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ 272 | FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ 273 | FRESULT f_chdir (const TCHAR* path); /* Change current directory */ 274 | FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ 275 | FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ 276 | FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ 277 | FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ 278 | FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ 279 | FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ 280 | FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */ 281 | FRESULT is_mounted(const TCHAR* path); 282 | FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ 283 | FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ 284 | FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ 285 | FRESULT f_setcp (WORD cp); /* Set current code page */ 286 | int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ 287 | int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ 288 | int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ 289 | TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ 290 | 291 | #define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) 292 | #define f_error(fp) ((fp)->err) 293 | #define f_tell(fp) ((fp)->fptr) 294 | #define f_size(fp) ((fp)->obj.objsize) 295 | #define f_rewind(fp) f_lseek((fp), 0) 296 | #define f_rewinddir(dp) f_readdir((dp), 0) 297 | #define f_rmdir(path) f_unlink(path) 298 | #define f_unmount(path) f_mount(0, path, 0) 299 | 300 | #ifndef EOF 301 | #define EOF (-1) 302 | #endif 303 | 304 | 305 | 306 | 307 | /*--------------------------------------------------------------*/ 308 | /* Additional user defined functions */ 309 | 310 | /* RTC function */ 311 | #if !FF_FS_READONLY && !FF_FS_NORTC 312 | DWORD get_fattime (void); 313 | #endif 314 | 315 | /* LFN support functions */ 316 | #if FF_USE_LFN /* Code conversion (defined in unicode.c) */ 317 | WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ 318 | WCHAR ff_uni2oem (WCHAR uni, WORD cp); /* Unicode to OEM code conversion */ 319 | WCHAR ff_wtoupper (WCHAR uni); /* Unicode upper-case conversion */ 320 | #endif 321 | #if FF_USE_LFN == 3 /* Dynamic memory allocation */ 322 | void* ff_memalloc (UINT msize); /* Allocate memory block */ 323 | void ff_memfree (void* mblock); /* Free memory block */ 324 | #endif 325 | 326 | /* Sync functions */ 327 | #if FF_FS_REENTRANT 328 | int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */ 329 | int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */ 330 | void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */ 331 | int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ 332 | #endif 333 | 334 | 335 | 336 | 337 | /*--------------------------------------------------------------*/ 338 | /* Flags and offset address */ 339 | 340 | 341 | /* File access mode and open method flags (3rd argument of f_open) */ 342 | #define FA_READ 0x01 343 | #define FA_WRITE 0x02 344 | #define FA_OPEN_EXISTING 0x00 345 | #define FA_CREATE_NEW 0x04 346 | #define FA_CREATE_ALWAYS 0x08 347 | #define FA_OPEN_ALWAYS 0x10 348 | #define FA_OPEN_APPEND 0x30 349 | 350 | /* Fast seek controls (2nd argument of f_lseek) */ 351 | #define CREATE_LINKMAP ((FSIZE_t)0 - 1) 352 | 353 | /* Format options (2nd argument of f_mkfs) */ 354 | #define FM_FAT 0x01 355 | #define FM_FAT32 0x02 356 | #define FM_EXFAT 0x04 357 | #define FM_ANY 0x07 358 | #define FM_SFD 0x08 359 | 360 | /* Filesystem type (FATFS.fs_type) */ 361 | #define FS_FAT12 1 362 | #define FS_FAT16 2 363 | #define FS_FAT32 3 364 | #define FS_EXFAT 4 365 | 366 | /* File attribute bits for directory entry (FILINFO.fattrib) */ 367 | #define AM_RDO 0x01 /* Read only */ 368 | #define AM_HID 0x02 /* Hidden */ 369 | #define AM_SYS 0x04 /* System */ 370 | #define AM_DIR 0x10 /* Directory */ 371 | #define AM_ARC 0x20 /* Archive */ 372 | 373 | 374 | #ifdef __cplusplus 375 | } 376 | #endif 377 | 378 | #endif /* FF_DEFINED */ 379 | --------------------------------------------------------------------------------