freemyipod r22 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r21‎ | r22 | r23 >
Date:03:51, 5 August 2010
Author:cmwslw
Status:new
Tags:
Comment:
Created branch for 4G development starting from r13.
Modified paths:
  • /embios/branches/4g_compat (added) (history)

Diff [purge]

Index: embios/branches/4g_compat/Makefile
@@ -0,0 +1,66 @@
 2+NAME := embios
 3+TARGETS := ipodnano2g ipodnano4g
 4+
 5+CROSS := arm-none-eabi-
 6+CC := $(CROSS)gcc
 7+AS := $(CROSS)as
 8+LD := $(CROSS)ld
 9+OBJCOPY := $(CROSS)objcopy
 10+UCLPACK := ucl2e10singleblk
 11+
 12+CFLAGS ?= -Os -fno-pie -fno-stack-protector -fomit-frame-pointer -I. -ffunction-sections -fdata-sections -std=gnu99
 13+LDFLAGS ?= "$(shell $(CC) -print-libgcc-file-name)" --gc-sections
 14+
 15+preprocess = $(shell $(CC) $(PPCFLAGS) $(2) -E -P -x c $(1) | grep -v "^\#" | sed -e "s:^..*:$(dir $(1))&:")
 16+
 17+define TARGET_template
 18+SRC_$(1) := $$(call preprocess,SOURCES,-DTARGET_$(1))
 19+OBJ_$(1) := $$(SRC_$(1):%.c=build/$(1)/%.o)
 20+OBJ_$(1) := $$(OBJ_$(1):%.S=build/$(1)/%.o)
 21+
 22+-include $$(OBJ_$(1):%=%.dep)
 23+
 24+$(1): build/$(1)/$(NAME)-$(1).ucl
 25+
 26+build/$(1)/$(NAME)-$(1).ucl: build/$(1)/$(NAME).bin
 27+ $(UCLPACK) $$^ $$@
 28+
 29+build/$(1)/$(NAME).bin: build/$(1)/$(NAME).elf
 30+ $(OBJCOPY) -O binary $$^ $$@
 31+
 32+build/$(1)/$(NAME).elf: target/$(1)/ls.x build/$(1)/target/$(1)/crt0.o $$(OBJ_$(1))
 33+ $(LD) $(LDFLAGS) -o $$@ -T target/$(1)/ls.x $$(OBJ_$(1))
 34+
 35+build/$(1)/%.o: %.c
 36+ifeq ($(shell uname),WindowsNT)
 37+ @-if not exist $$(subst /,\,$$(dir $$@)) md $$(subst /,\,$$(dir $$@))
 38+else
 39+ @-mkdir -p $$(dir $$@)
 40+endif
 41+ $(CC) -c $(CFLAGS) -Itarget/$(1) -DTARGET_$(1) -o $$@ $$<
 42+ @$(CC) -MM $(CFLAGS) -Itarget/$(1) -DTARGET_$(1) $$< > $$@.dep.tmp
 43+ @sed -e "s|.*:|$$@:|" < $$@.dep.tmp > $$@.dep
 44+ @sed -e "s/.*://" -e "s/\\$$$$//" < $$@.dep.tmp | fmt -1 | sed -e "s/^ *//" -e "s/$$$$/:/" >> $$@.dep
 45+ @rm -f $$@.dep.tmp
 46+
 47+build/$(1)/%.o: %.S
 48+ifeq ($(shell uname),WindowsNT)
 49+ @-if not exist $$(subst /,\,$$(dir $$@)) md $$(subst /,\,$$(dir $$@))
 50+else
 51+ @-mkdir -p $$(dir $$@)
 52+endif
 53+ $(CC) -c $(CFLAGS) -Itarget/$(1) -DTARGET_$(1) -o $$@ $$<
 54+ @$(CC) -MM $(CFLAGS) -Itarget/$(1) -DTARGET_$(1) $$< > $$@.dep.tmp
 55+ @sed -e "s|.*:|$$@:|" < $$@.dep.tmp > $$@.dep
 56+ @sed -e "s/.*://" -e "s/\\$$$$//" < $$@.dep.tmp | fmt -1 | sed -e "s/^ *//" -e "s/$$$$/:/" >> $$@.dep
 57+ @rm -f $$@.dep.tmp
 58+endef
 59+
 60+all: $(TARGETS)
 61+
 62+$(foreach target,$(TARGETS),$(eval $(call TARGET_template,$(target))))
 63+
 64+clean:
 65+ rm -rf build
 66+
 67+.PHONY: all clean $(TARGETS)
Index: embios/branches/4g_compat/SOURCES
@@ -0,0 +1,28 @@
 2+#ifdef TARGET_ipodnano2g
 3+target/ipodnano2g/mmu.c
 4+target/ipodnano2g/lcd.c
 5+target/ipodnano2g/nand.c
 6+target/ipodnano2g/storage.c
 7+target/ipodnano2g/i2c.S
 8+#endif
 9+
 10+#ifdef TARGET_ipodnano4g
 11+target/ipodnano4g/mmu.c
 12+target/ipodnano4g/lcd.c
 13+target/ipodnano4g/storage.c
 14+#endif
 15+
 16+init.c
 17+main.c
 18+util.c
 19+drawing.S
 20+lcdconsole.c
 21+format.c
 22+snprintf.c
 23+panic.c
 24+console.c
 25+arm-support.S
 26+strlen.c
 27+fat32.c
 28+ucl.S
 29+
Index: embios/branches/4g_compat/target/ipodnano4g/mmu.c
@@ -0,0 +1,34 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+#include "mmu.h"
 27+
 28+
 29+void clean_dcache()
 30+{
 31+}
 32+
 33+void invalidate_dcache()
 34+{
 35+}
Index: embios/branches/4g_compat/target/ipodnano4g/lcd.S
@@ -0,0 +1,92 @@
 2+@
 3+@
 4+@ Copyright 2010 TheSeven
 5+@
 6+@
 7+@ This file is part of emBIOS.
 8+@
 9+@ emBIOS is free software: you can redistribute it and/or
 10+@ modify it under the terms of the GNU General Public License as
 11+@ published by the Free Software Foundation, either version 2 of the
 12+@ License, or (at your option) any later version.
 13+@
 14+@ emBIOS is distributed in the hope that it will be useful,
 15+@ but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+@ See the GNU General Public License for more details.
 18+@
 19+@ You should have received a copy of the GNU General Public License
 20+@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+@
 22+@
 23+
 24+
 25+.section .icode.displaylcd, "ax", %progbits
 26+.align 2
 27+.global displaylcd
 28+.type displaylcd, %function
 29+displaylcd:
 30+ stmfd sp!, {r0,r1,r4,lr}
 31+ mov r12, #0x38000000
 32+ orr r12, r12, #0x300000
 33+ mov r0, #0x2a
 34+ bl displaylcd_sendlcdc
 35+ ldr r0, [sp]
 36+ bl displaylcd_sendlcdd
 37+ ldr r0, [sp,#0x04]
 38+ bl displaylcd_sendlcdd
 39+ mov r0, #0x2b
 40+ bl displaylcd_sendlcdc
 41+ mov r0, r2
 42+ tst r0, #0x100
 43+ eorne r0, #0x300
 44+ bl displaylcd_sendlcdd
 45+ mov r0, r3
 46+ tst r0, #0x100
 47+ eorne r0, #0x300
 48+ bl displaylcd_sendlcdd
 49+ mov r0, #0x2c
 50+ bl displaylcd_sendlcdc
 51+ ldmia sp, {r0,r1}
 52+ sub r1, r0
 53+ add r1, r1, #1
 54+ sub r3, r2
 55+ add r3, r3, #1
 56+ mul r2, r1, r3
 57+ ldr r1, [sp,#0x10]
 58+ cmp r1, #0x40000000
 59+ bne displaylcd_framebuf
 60+displaylcd_color:
 61+ ldr r0, [sp,#0x14]
 62+ bl displaylcd_sendlcdd
 63+ subs r2, r2, #1
 64+ bne displaylcd_color
 65+ ldmfd sp!, {r4-r6,pc}
 66+displaylcd_framebuf:
 67+ ldrh r0, [r1], #2
 68+ bl displaylcd_sendlcdd
 69+ subs r2, r2, #1
 70+ bne displaylcd_framebuf
 71+ ldmfd sp!, {r0,r1,r4,pc}
 72+
 73+displaylcd_sendlcdc:
 74+ ldrh r4, [r12,#0x1c]
 75+ tst r4, #0x10
 76+ bne displaylcd_sendlcdc
 77+ strh r0, [r12,#0x04]
 78+ mov pc, lr
 79+displaylcd_sendlcdd:
 80+ ldrh r4, [r12,#0x1c]
 81+ tst r4, #0x10
 82+ bne displaylcd_sendlcdd
 83+ strh r0, [r12,#0x40]
 84+ mov pc, lr
 85+.size displaylcd, .-displaylcd
 86+
 87+.section .icode.displaylcd_sync, "ax", %progbits
 88+.align 2
 89+.global displaylcd_sync
 90+.type displaylcd_sync, %function
 91+displaylcd_sync:
 92+ mov pc, lr
 93+.size displaylcd_sync, .-displaylcd_sync
Index: embios/branches/4g_compat/target/ipodnano4g/ls.x
@@ -0,0 +1,101 @@
 2+ENTRY(_start)
 3+OUTPUT_FORMAT(elf32-littlearm)
 4+OUTPUT_ARCH(arm)
 5+STARTUP(build/ipodnano4g/target/ipodnano4g/crt0.o)
 6+
 7+MEMORY
 8+{
 9+ INIT : ORIGIN = 0x08000000, LENGTH = 0x01f00000
 10+ SRAM : ORIGIN = 0x22000000, LENGTH = 0x00030000
 11+ SDRAM : ORIGIN = 0x09f00000, LENGTH = 0x00100000
 12+}
 13+
 14+SECTIONS
 15+{
 16+ .init : {
 17+ *(.initcode*)
 18+ *(.initrodata*)
 19+ *(.initdata*)
 20+ . = ALIGN(0x4);
 21+ } > INIT
 22+
 23+ .intvect : {
 24+ _sramstart = .;
 25+ KEEP(*(.intvect))
 26+ *(.intvect)
 27+ } > SRAM AT> INIT
 28+ _sramsource = LOADADDR(.intvect);
 29+
 30+ .iram :
 31+ {
 32+ *(.icode*)
 33+ *(.irodata*)
 34+ *(.idata*)
 35+ . = ALIGN(0x4);
 36+ _sramend = .;
 37+ } > SRAM AT> INIT
 38+
 39+ .text :
 40+ {
 41+ _sdramstart = .;
 42+ *(.text*)
 43+ *(.glue_7)
 44+ *(.glue_7t)
 45+ . = ALIGN(0x4);
 46+ } > SDRAM AT> INIT
 47+ _sdramsource = LOADADDR(.text);
 48+
 49+ .rodata :
 50+ {
 51+ *(.rodata*)
 52+ . = ALIGN(0x4);
 53+ } > SDRAM AT> INIT
 54+
 55+ .data :
 56+ {
 57+ *(.data*)
 58+ . = ALIGN(0x4);
 59+ _sdramend = .;
 60+ } > SDRAM AT> INIT
 61+
 62+ .initbss (NOLOAD) :
 63+ {
 64+ _initbssstart = .;
 65+ *(.initbss*)
 66+ . = ALIGN(0x4);
 67+ _initstackstart = .;
 68+ . += 0x4000;
 69+ _initstackend = .;
 70+ _initbssend = .;
 71+ } > INIT
 72+
 73+ .ibss (NOLOAD) :
 74+ {
 75+ _ibssstart = .;
 76+ *(.ibss*)
 77+ . = ALIGN(0x4);
 78+ _irqstackstart = .;
 79+ . += 0x400;
 80+ _irqstackend = .;
 81+ _abortstackstart = .;
 82+ . += 0x400;
 83+ _abortstackend = .;
 84+ *(.stack)
 85+ _ibssend = .;
 86+ } > SRAM
 87+
 88+ .bss (NOLOAD) :
 89+ {
 90+ _bssstart = .;
 91+ *(.bss*)
 92+ *(COMMON)
 93+ . = ALIGN(0x4);
 94+ _bssend = .;
 95+ } > SDRAM
 96+
 97+ /DISCARD/ :
 98+ {
 99+ *(.eh_frame)
 100+ }
 101+
 102+}
Index: embios/branches/4g_compat/target/ipodnano4g/mmu.h
@@ -0,0 +1,35 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __MMU_H__
 26+#define __MMU_H__
 27+
 28+
 29+#include "global.h"
 30+
 31+
 32+void clean_dcache() __attribute__((naked, noinline)) ICODE_ATTR;
 33+void invalidate_dcache() __attribute__((naked, noinline)) ICODE_ATTR;
 34+
 35+
 36+#endif
Index: embios/branches/4g_compat/target/ipodnano4g/storage.c
@@ -0,0 +1,51 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+
 26+#include "global.h"
 27+#include "storage.h"
 28+
 29+uint32_t storage_init()
 30+{
 31+ return -1;
 32+}
 33+
 34+uint32_t storage_read(uint32_t sector, uint32_t count, void* buffer)
 35+{
 36+ return -1;
 37+}
 38+
 39+uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer)
 40+{
 41+ return -1;
 42+}
 43+
 44+uint32_t storage_sync()
 45+{
 46+ return -1;
 47+}
 48+
 49+uint32_t storage_get_sector_count()
 50+{
 51+ return -1;
 52+}
Index: embios/branches/4g_compat/target/ipodnano4g/timer.h
@@ -0,0 +1,42 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __TIMER_H__
 26+#define __TIMER_H__
 27+
 28+#include "global.h"
 29+
 30+
 31+#define TIME_AFTER(a,b) ((long)(b) - (long)(a) < 0)
 32+#define TIME_BEFORE(a,b) TIME_AFTER(b,a)
 33+#define TIMEOUT_EXPIRED(a,b) TIME_AFTER(USEC_TIMER,a + b)
 34+
 35+
 36+static inline void sleep(long duration) /* in usec steps */
 37+{
 38+ long timestamp = USEC_TIMER;
 39+ while (!TIMEOUT_EXPIRED(timestamp, duration));
 40+}
 41+
 42+
 43+#endif
Index: embios/branches/4g_compat/target/ipodnano4g/lcd.h
@@ -0,0 +1,43 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __LCD_H__
 26+#define __LCD_H__
 27+
 28+
 29+#include "global.h"
 30+
 31+
 32+#define LCD_WIDTH 240
 33+#define LCD_HEIGHT 320
 34+#define LCD_FORMAT rgb565
 35+#define LCD_BYTESPERPIXEL 2
 36+#define LCD_FRAMEBUFSIZE (LCD_WIDTH * LCD_HEIGHT * LCD_BYTESPERPIXEL)
 37+
 38+
 39+void displaylcd(unsigned int startx, unsigned int endx,
 40+ unsigned int starty, unsigned int endy, void* data, int color);
 41+void displaylcd_sync();
 42+
 43+
 44+#endif
Index: embios/branches/4g_compat/target/ipodnano4g/crt0.S
@@ -0,0 +1,182 @@
 2+@
 3+@
 4+@ Copyright 2010 TheSeven
 5+@
 6+@
 7+@ This file is part of emBIOS.
 8+@
 9+@ emBIOS is free software: you can redistribute it and/or
 10+@ modify it under the terms of the GNU General Public License as
 11+@ published by the Free Software Foundation, either version 2 of the
 12+@ License, or (at your option) any later version.
 13+@
 14+@ emBIOS is distributed in the hope that it will be useful,
 15+@ but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+@ See the GNU General Public License for more details.
 18+@
 19+@ You should have received a copy of the GNU General Public License
 20+@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+@
 22+@
 23+
 24+
 25+.section .intvect,"ax",%progbits
 26+ ldr pc, =reset_handler
 27+ ldr pc, =undef_instr_handler
 28+ ldr pc, =syscall_handler
 29+ ldr pc, =prefetch_abort_handler
 30+ ldr pc, =data_abort_handler
 31+ ldr pc, =reserved_handler
 32+ ldr pc, =irq_handler
 33+ ldr pc, =fiq_handler
 34+.ltorg
 35+
 36+
 37+.section .initcode,"ax",%progbits
 38+.global _start
 39+_start:
 40+ ldr r0, =_sramsource
 41+ ldr r1, =_sramstart
 42+ ldr r2, =_sramend
 43+.copysram:
 44+ cmp r2, r1
 45+ ldrhi r3, [r0], #4
 46+ strhi r3, [r1], #4
 47+ bhi .copysram
 48+ ldr r0, =_sdramsource
 49+ ldr r1, =_sdramstart
 50+ ldr r2, =_sdramend
 51+.copysdram:
 52+ cmp r2, r1
 53+ ldrhi r3, [r0], #4
 54+ strhi r3, [r1], #4
 55+ bhi .copysdram
 56+ ldr r0, =_initbssstart
 57+ ldr r1, =_initbssend
 58+ mov r2, #0
 59+.clearinitbss:
 60+ cmp r1, r0
 61+ strhi r2, [r0], #4
 62+ bhi .clearinitbss
 63+ ldr r0, =_ibssstart
 64+ ldr r1, =_ibssend
 65+.clearibss:
 66+ cmp r1, r0
 67+ strhi r2, [r0], #4
 68+ bhi .clearibss
 69+ ldr r0, =_bssstart
 70+ ldr r1, =_bssend
 71+.clearbss:
 72+ cmp r1, r0
 73+ strhi r2, [r0], #4
 74+ bhi .clearbss
 75+ ldr r1, =0x38200000
 76+ ldr r0, [r1]
 77+ orr r0, r0, #1
 78+ bic r0, r0, #0x10000
 79+ str r0, [r1]
 80+ mov r0, #0
 81+ mcr p15, 0, r0,c7,c5,0
 82+ msr cpsr_c, #0xd2
 83+ ldr sp, =_irqstackend
 84+ msr cpsr_c, #0xd7
 85+ ldr sp, =_abortstackend
 86+ msr cpsr_c, #0xdb
 87+ ldr sp, =_abortstackend
 88+ msr cpsr_c, #0xd3
 89+ ldr sp, =_initstackend
 90+ bl init
 91+ b main
 92+.ltorg
 93+
 94+
 95+.section .icode, "ax", %progbits
 96+.align 2
 97+.global reset
 98+.global hang
 99+.type reset, %function
 100+.type hang, %function
 101+reset:
 102+ msr cpsr_c, #0xd3
 103+ mov r0, #0x100000
 104+ mov r1, #0x3c800000
 105+ str r0, [r1]
 106+hang:
 107+ b hang
 108+.size reset, .-reset
 109+.size hang, .-hang
 110+
 111+.type reset_handler, %function
 112+reset_handler:
 113+ adr r0, reset_text
 114+ b panic
 115+reset_text:
 116+ .ascii "Hit reset vector!\0"
 117+.size reset_handler, .-reset_handler
 118+
 119+.type undef_instr_handler, %function
 120+undef_instr_handler:
 121+ adr r0, undef_instr_text
 122+ sub r0, lr, #4
 123+ b panicf
 124+.size undef_instr_handler, .-undef_instr_handler
 125+
 126+.type prefetch_abort_handler, %function
 127+prefetch_abort_handler:
 128+ adr r0, prefetch_abort_text
 129+ sub r0, lr, #4
 130+ b panicf
 131+.size prefetch_abort_handler, .-prefetch_abort_handler
 132+
 133+.type data_abort_handler, %function
 134+data_abort_handler:
 135+ adr r0, data_abort_text
 136+ sub r0, lr, #4
 137+ b panicf
 138+.size data_abort_handler, .-data_abort_handler
 139+
 140+.type reserved_handler, %function
 141+reserved_handler:
 142+ adr r0, reserved_text
 143+ b panic
 144+.size reserved_handler, .-reserved_handler
 145+
 146+.type fiq_handler, %function
 147+fiq_handler:
 148+ adr r0, fiq_text
 149+ b panic
 150+.size fiq_handler, .-fiq_handler
 151+
 152+.type irq_handler, %function
 153+irq_handler:
 154+ adr r0, irq_text
 155+ b panic
 156+.size irq_handler, .-irq_handler
 157+
 158+.type syscall_handler, %function
 159+syscall_handler:
 160+ adr r0, syscall_text
 161+ b panic
 162+.size syscall_handler, .-syscall_handler
 163+
 164+undef_instr_text:
 165+ .ascii "Undefined instruction at %08X!\0"
 166+
 167+prefetch_abort_text:
 168+ .ascii "Prefetch abort at %08X!\0"
 169+
 170+data_abort_text:
 171+ .ascii "Data abort at %08X!\0"
 172+
 173+reserved_text:
 174+ .ascii "Hit reserved exception handler!\0"
 175+
 176+fiq_text:
 177+ .ascii "Unhandled FIQ!\0"
 178+
 179+irq_text:
 180+ .ascii "Unhandled IRQ!\0"
 181+
 182+syscall_text:
 183+ .ascii "Unhandled syscall!\0"
Index: embios/branches/4g_compat/target/ipodnano4g/storage.h
@@ -0,0 +1,36 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __FTL_H__
 26+#define __FTL_H__
 27+
 28+#include "global.h"
 29+
 30+uint32_t storage_init();
 31+uint32_t storage_read(uint32_t sector, uint32_t count, void* buffer);
 32+uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer);
 33+uint32_t storage_sync();
 34+uint32_t storage_get_sector_count();
 35+
 36+
 37+#endif
Index: embios/branches/4g_compat/target/ipodnano4g/config.h
@@ -0,0 +1,28 @@
 2+//
 3+//
 4+// Copyright 2009 TheSeven
 5+//
 6+//
 7+// This file is part of the Linux4Nano toolkit.
 8+//
 9+// TheSeven's iBugger is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// TheSeven's iBugger is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+//#define NAND_DEBUG
 26+//#define NAND_TRACE
 27+//#define VFL_TRACE
 28+//#define FTL_TRACE
 29+
Index: embios/branches/4g_compat/target/ipodnano4g/target.h
@@ -0,0 +1,31 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __TARGET_H__
 26+#define __TARGET_H__
 27+
 28+
 29+#define ARM_ARCH 6
 30+
 31+
 32+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/lcd.S
@@ -0,0 +1,165 @@
 2+@
 3+@
 4+@ Copyright 2010 TheSeven
 5+@
 6+@
 7+@ This file is part of emBIOS.
 8+@
 9+@ emBIOS is free software: you can redistribute it and/or
 10+@ modify it under the terms of the GNU General Public License as
 11+@ published by the Free Software Foundation, either version 2 of the
 12+@ License, or (at your option) any later version.
 13+@
 14+@ emBIOS is distributed in the hope that it will be useful,
 15+@ but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+@ See the GNU General Public License for more details.
 18+@
 19+@ You should have received a copy of the GNU General Public License
 20+@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+@
 22+@
 23+
 24+
 25+.section .icode.displaylcd, "ax", %progbits
 26+.align 2
 27+.global displaylcd
 28+.type displaylcd, %function
 29+displaylcd:
 30+ stmfd sp!, {r0,r1,r4,lr}
 31+ bl displaylcd_sync
 32+ bl displaylcd_detectlcd
 33+ sub r12, r12, #0x04900000
 34+ cmp r0, #2
 35+ bne displaylcd_othertypes
 36+ mov r0, #0x50
 37+ bl displaylcd_sendlcd2c
 38+ ldr r0, [sp]
 39+ bl displaylcd_sendlcd2d
 40+ mov r0, #0x51
 41+ bl displaylcd_sendlcd2c
 42+ ldr r0, [sp,#0x04]
 43+ bl displaylcd_sendlcd2d
 44+ mov r0, #0x52
 45+ bl displaylcd_sendlcd2c
 46+ mov r0, r2
 47+ bl displaylcd_sendlcd2d
 48+ mov r0, #0x53
 49+ bl displaylcd_sendlcd2c
 50+ mov r0, r3
 51+ bl displaylcd_sendlcd2d
 52+ mov r0, #0x20
 53+ bl displaylcd_sendlcd2c
 54+ ldr r0, [sp]
 55+ bl displaylcd_sendlcd2d
 56+ mov r0, #0x21
 57+ bl displaylcd_sendlcd2c
 58+ mov r0, r2
 59+ bl displaylcd_sendlcd2d
 60+ mov r0, #0x22
 61+ bl displaylcd_sendlcd2c
 62+ b displaylcd_blit
 63+displaylcd_othertypes:
 64+ mov r0, #0x2a
 65+ bl displaylcd_sendlcdc
 66+ ldr r0, [sp]
 67+ bl displaylcd_sendlcd2d
 68+ ldr r0, [sp,#0x04]
 69+ bl displaylcd_sendlcd2d
 70+ mov r0, #0x2b
 71+ bl displaylcd_sendlcdc
 72+ mov r0, r2
 73+ bl displaylcd_sendlcd2d
 74+ mov r0, r3
 75+ bl displaylcd_sendlcd2d
 76+ mov r0, #0x2c
 77+ bl displaylcd_sendlcdc
 78+displaylcd_blit:
 79+ ldmia sp, {r0,r1}
 80+ sub r1, r0
 81+ add r1, r1, #1
 82+ sub r3, r2
 83+ add r3, r3, #1
 84+ mul r2, r1, r3
 85+ ldr r1, [sp,#0x10]
 86+ cmp r1, #0x40000000
 87+ bne displaylcd_dma
 88+displaylcd_pixel:
 89+ ldr r0, [sp,#0x14]
 90+ bl displaylcd_sendlcd2d
 91+ subs r2, r2, #1
 92+ bne displaylcd_pixel
 93+ ldmfd sp!, {r0,r1,r4,pc}
 94+displaylcd_dma:
 95+ mov r4, #0x38000000
 96+ add r4, r4, #0x400000
 97+ mov r0, #0x20000000
 98+ orr r0, r0, #0x180000
 99+ str r0, [r4,#0x104]
 100+ str r1, [r4,#0x100]
 101+ mov r0, r2,lsr#1
 102+ sub r0, r0, #1
 103+ str r0, [r4,#0x108]
 104+ bl clean_dcache
 105+ mov r0, #4
 106+ str r0, [r4,#0x114]
 107+ ldmfd sp!, {r0,r1,r4,pc}
 108+
 109+displaylcd_sendlcd2c:
 110+ ldr r4, [r12,#0x1c]
 111+ tst r4, #0x10
 112+ bne displaylcd_sendlcd2c
 113+ mov r4, r0,lsr#8
 114+ str r4, [r12,#0x04]
 115+ and r0, r0, #0xff
 116+displaylcd_sendlcdc:
 117+ ldrh r4, [r12,#0x1c]
 118+ tst r4, #0x10
 119+ bne displaylcd_sendlcdc
 120+ strh r0, [r12,#0x04]
 121+ mov pc, lr
 122+displaylcd_sendlcd2d:
 123+ ldrh r4, [r12,#0x1c]
 124+ tst r4, #0x10
 125+ bne displaylcd_sendlcd2d
 126+ mov r4, r0,lsr#8
 127+ strh r4, [r12,#0x40]
 128+ and r0, r0, #0xff
 129+displaylcd_sendlcdd:
 130+ ldrh r4, [r12,#0x1c]
 131+ tst r4, #0x10
 132+ bne displaylcd_sendlcdd
 133+ strh r0, [r12,#0x40]
 134+ mov pc, lr
 135+
 136+displaylcd_detectlcd:
 137+ mov r12, #0x3c000000
 138+ orr r12, r12, #0xf00000
 139+ ldr r0, [r12,#0xd0]
 140+ bic r0, r0, #0x0f
 141+ str r0, [r12,#0xd0]
 142+ ldr r0, [r12,#0xe0]
 143+ bic r0, r0, #0xf0
 144+ str r0, [r12,#0xe0]
 145+ ldr r0, [r12,#0xd4]
 146+ and r0, r0, #1
 147+ ldr r1, [r12,#0xe4]
 148+ and r1, r1, #2
 149+ orr r0, r0, r1
 150+ mov pc, lr
 151+.size displaylcd, .-displaylcd
 152+
 153+
 154+.section .icode.displaylcd_sync, "ax", %progbits
 155+.align 2
 156+.global displaylcd_sync
 157+.type displaylcd_sync, %function
 158+displaylcd_sync:
 159+ mov r1, #0x38000000
 160+ add r1, r1, #0x400000
 161+displaylcd_sync_wait:
 162+ ldr r0, [r1,#0x184]
 163+ tst r0, #0x40000
 164+ bne displaylcd_sync_wait
 165+ mov pc, lr
 166+.size displaylcd_sync, .-displaylcd_sync
Index: embios/branches/4g_compat/target/ipodnano2g/mmu.c
@@ -0,0 +1,64 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+#include "mmu.h"
 27+
 28+
 29+void clean_dcache()
 30+{
 31+ asm volatile(
 32+ "MOV R0, #0 \n\t"
 33+ "clean_dcache_loop: \n\t"
 34+ "MCR p15, 0, R0,c7,c10,2 \n\t"
 35+ "ADD R1, R0, #0x10 \n\t"
 36+ "MCR p15, 0, R1,c7,c10,2 \n\t"
 37+ "ADD R1, R1, #0x10 \n\t"
 38+ "MCR p15, 0, R1,c7,c10,2 \n\t"
 39+ "ADD R1, R1, #0x10 \n\t"
 40+ "MCR p15, 0, R1,c7,c10,2 \n\t"
 41+ "ADDS R0, R0, #0x04000000 \n\t"
 42+ "BNE clean_dcache_loop \n\t"
 43+ "MCR p15, 0, R0,c7,c10,4 \n\t"
 44+ "MOV PC, LR \n\t"
 45+ );
 46+}
 47+
 48+void invalidate_dcache()
 49+{
 50+ asm volatile(
 51+ "MOV R0, #0 \n\t"
 52+ "invalidate_dcache_loop: \n\t"
 53+ "MCR p15, 0, R0,c7,c14,2 \n\t"
 54+ "ADD R1, R0, #0x10 \n\t"
 55+ "MCR p15, 0, R1,c7,c14,2 \n\t"
 56+ "ADD R1, R1, #0x10 \n\t"
 57+ "MCR p15, 0, R1,c7,c14,2 \n\t"
 58+ "ADD R1, R1, #0x10 \n\t"
 59+ "MCR p15, 0, R1,c7,c14,2 \n\t"
 60+ "ADDS R0, R0, #0x04000000 \n\t"
 61+ "BNE invalidate_dcache_loop\n\t"
 62+ "MCR p15, 0, R0,c7,c10,4 \n\t"
 63+ "MOV PC, LR \n\t"
 64+ );
 65+}
Index: embios/branches/4g_compat/target/ipodnano2g/ls.x
@@ -0,0 +1,101 @@
 2+ENTRY(_start)
 3+OUTPUT_FORMAT(elf32-littlearm)
 4+OUTPUT_ARCH(arm)
 5+STARTUP(build/ipodnano2g/target/ipodnano2g/crt0.o)
 6+
 7+MEMORY
 8+{
 9+ INIT : ORIGIN = 0x08000000, LENGTH = 0x01f00000
 10+ SRAM : ORIGIN = 0x22000000, LENGTH = 0x0002bdf0
 11+ SDRAM : ORIGIN = 0x09f00000, LENGTH = 0x00100000
 12+}
 13+
 14+SECTIONS
 15+{
 16+ .init : {
 17+ *(.initcode*)
 18+ *(.initrodata*)
 19+ *(.initdata*)
 20+ . = ALIGN(0x4);
 21+ } > INIT
 22+
 23+ .intvect : {
 24+ _sramstart = .;
 25+ KEEP(*(.intvect))
 26+ *(.intvect)
 27+ } > SRAM AT> INIT
 28+ _sramsource = LOADADDR(.intvect);
 29+
 30+ .iram :
 31+ {
 32+ *(.icode*)
 33+ *(.irodata*)
 34+ *(.idata*)
 35+ . = ALIGN(0x4);
 36+ _sramend = .;
 37+ } > SRAM AT> INIT
 38+
 39+ .text :
 40+ {
 41+ _sdramstart = .;
 42+ *(.text*)
 43+ *(.glue_7)
 44+ *(.glue_7t)
 45+ . = ALIGN(0x4);
 46+ } > SDRAM AT> INIT
 47+ _sdramsource = LOADADDR(.text);
 48+
 49+ .rodata :
 50+ {
 51+ *(.rodata*)
 52+ . = ALIGN(0x4);
 53+ } > SDRAM AT> INIT
 54+
 55+ .data :
 56+ {
 57+ *(.data*)
 58+ . = ALIGN(0x4);
 59+ _sdramend = .;
 60+ } > SDRAM AT> INIT
 61+
 62+ .initbss (NOLOAD) :
 63+ {
 64+ _initbssstart = .;
 65+ *(.initbss*)
 66+ . = ALIGN(0x4);
 67+ _initstackstart = .;
 68+ . += 0x4000;
 69+ _initstackend = .;
 70+ _initbssend = .;
 71+ } > INIT
 72+
 73+ .ibss (NOLOAD) :
 74+ {
 75+ _ibssstart = .;
 76+ *(.ibss*)
 77+ . = ALIGN(0x4);
 78+ _irqstackstart = .;
 79+ . += 0x400;
 80+ _irqstackend = .;
 81+ _abortstackstart = .;
 82+ . += 0x400;
 83+ _abortstackend = .;
 84+ *(.stack)
 85+ _ibssend = .;
 86+ } > SRAM
 87+
 88+ .bss (NOLOAD) :
 89+ {
 90+ _bssstart = .;
 91+ *(.bss*)
 92+ *(COMMON)
 93+ . = ALIGN(0x4);
 94+ _bssend = .;
 95+ } > SDRAM
 96+
 97+ /DISCARD/ :
 98+ {
 99+ *(.eh_frame)
 100+ }
 101+
 102+}
Index: embios/branches/4g_compat/target/ipodnano2g/mmu.h
@@ -0,0 +1,35 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __MMU_H__
 26+#define __MMU_H__
 27+
 28+
 29+#include "global.h"
 30+
 31+
 32+void clean_dcache() __attribute__((naked, noinline)) ICODE_ATTR;
 33+void invalidate_dcache() __attribute__((naked, noinline)) ICODE_ATTR;
 34+
 35+
 36+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/storage.c
@@ -0,0 +1,1848 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+
 26+#include "global.h"
 27+#include "nand.h"
 28+#include "storage.h"
 29+#include "util.h"
 30+
 31+
 32+
 33+//#define FTL_FORCEMOUNT
 34+
 35+
 36+
 37+#ifdef FTL_FORCEMOUNT
 38+#ifndef FTL_READONLY
 39+#define FTL_READONLY
 40+#endif
 41+#endif
 42+
 43+
 44+#ifdef FTL_READONLY
 45+uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer)
 46+{
 47+ (void)sector;
 48+ (void)count;
 49+ (void)buffer;
 50+ return -1;
 51+}
 52+uint32_t storage_sync(void)
 53+{
 54+ return 0;
 55+}
 56+#endif
 57+
 58+
 59+
 60+/* Keeps the state of a scattered page block.
 61+ This structure is used in memory only, not on flash,
 62+ but it equals the one the OFW uses. */
 63+struct ftl_log_type
 64+{
 65+
 66+ /* The ftl_cxt.nextblockusn at the time the block was allocated,
 67+ needed in order to be able to remove the oldest ones first. */
 68+ uint32_t usn;
 69+
 70+ /* The vBlock number at which the scattered pages are stored */
 71+ uint16_t scatteredvblock;
 72+
 73+ /* the lBlock number for which those pages are */
 74+ uint16_t logicalvblock;
 75+
 76+ /* Pointer to ftl_offsets, contains the mapping which lPage is
 77+ currently stored at which scattered vPage. */
 78+ uint16_t* pageoffsets;
 79+
 80+ /* Pages used in the vBlock, i.e. next page number to be written */
 81+ uint16_t pagesused;
 82+
 83+ /* Pages that are still up to date in this block, i.e. need to be
 84+ moved when this vBlock is deallocated. */
 85+ uint16_t pagescurrent;
 86+
 87+ /* A flag whether all pages are still sequential in this block.
 88+ Initialized to 1 on allocation, zeroed as soon as anything is
 89+ written out of sequence, so that the block will need copying
 90+ when committing to get the pages back into the right order.
 91+ This is used to half the number of block erases needed when
 92+ writing huge amounts of sequential data. */
 93+ uint32_t issequential;
 94+
 95+} __attribute__((packed));
 96+
 97+
 98+/* Keeps the state of the FTL, both on flash and in memory */
 99+struct ftl_cxt_type
 100+{
 101+
 102+ /* Update sequence number of the FTL context, decremented
 103+ every time a new revision of FTL meta data is written. */
 104+ uint32_t usn;
 105+
 106+ /* Update sequence number for user data blocks. Incremented
 107+ every time a portion of user pages is written, so that
 108+ a consistency check can determine which copy of a user
 109+ page is the most recent one. */
 110+ uint32_t nextblockusn;
 111+
 112+ /* Count of currently free pages in the block pool */
 113+ uint16_t freecount;
 114+
 115+ /* Index to the first free block in the blockpool ring buffer */
 116+ uint16_t nextfreeidx;
 117+
 118+ /* This is a counter that is used to better distribute block
 119+ wear. It is incremented on every block erase, and if it
 120+ gets too high (300 on writes, 20 on sync), the most and
 121+ least worn block will be swapped (inferring an additional
 122+ block write) and the counter will be decreased by 20. */
 123+ uint16_t swapcounter;
 124+
 125+ /* Ring buffer of currently free blocks. nextfreeidx is the
 126+ index to freecount free ones, the other ones are currently
 127+ allocated for scattered page blocks. */
 128+ uint16_t blockpool[0x14];
 129+
 130+ /* Alignment to 32 bits */
 131+ uint16_t field_36;
 132+
 133+ /* vPages where the block map is stored */
 134+ uint32_t ftl_map_pages[8];
 135+
 136+ /* Probably additional map page number space for bigger chips */
 137+ uint8_t field_58[0x28];
 138+
 139+ /* vPages where the erase counters are stored */
 140+ uint32_t ftl_erasectr_pages[8];
 141+
 142+ /* Seems to be padding */
 143+ uint8_t field_A0[0x70];
 144+
 145+ /* Pointer to ftl_map used by Whimory, not used by us */
 146+ uint32_t ftl_map_ptr;
 147+
 148+ /* Pointer to ftl_erasectr used by Whimory, not used by us */
 149+ uint32_t ftl_erasectr_ptr;
 150+
 151+ /* Pointer to ftl_log used by Whimory, not used by us */
 152+ uint32_t ftl_log_ptr;
 153+
 154+ /* Flag used to indicate that some erase counter pages should be committed
 155+ as they were changed more than 100 times since the last commit. */
 156+ uint32_t erasedirty;
 157+
 158+ /* Seems to be unused */
 159+ uint16_t field_120;
 160+
 161+ /* vBlocks used to store the FTL context, map, and erase
 162+ counter pages. This is also a ring buffer, and the oldest
 163+ page gets swapped with the least used page from the block
 164+ pool ring buffer when a new one is allocated. */
 165+ uint16_t ftlctrlblocks[3];
 166+
 167+ /* The last used vPage number from ftlctrlblocks */
 168+ uint32_t ftlctrlpage;
 169+
 170+ /* Set on context sync, reset on write, so obviously never
 171+ zero in the context written to the flash */
 172+ uint32_t clean_flag;
 173+
 174+ /* Seems to be unused, but gets loaded from flash by Whimory. */
 175+ uint8_t field_130[0x15C];
 176+
 177+} __attribute__((packed));
 178+
 179+
 180+/* Keeps the state of the bank's VFL, both on flash and in memory.
 181+ There is one of these per bank. */
 182+struct ftl_vfl_cxt_type
 183+{
 184+
 185+ /* Cross-bank update sequence number, incremented on every VFL
 186+ context commit on any bank. */
 187+ uint32_t usn;
 188+
 189+ /* See ftl_cxt.ftlctrlblocks. This is stored to the VFL contexts
 190+ in order to be able to find the most recent FTL context copy
 191+ when mounting the FTL. The VFL context number this will be
 192+ written to on an FTL context commit is chosen semi-randomly. */
 193+ uint16_t ftlctrlblocks[3];
 194+
 195+ /* Alignment to 32 bits */
 196+ uint8_t field_A[2];
 197+
 198+ /* Decrementing update counter for VFL context commits per bank */
 199+ uint32_t updatecount;
 200+
 201+ /* Number of the currently active VFL context block, it's an index
 202+ into vflcxtblocks. */
 203+ uint16_t activecxtblock;
 204+
 205+ /* Number of the first free page in the active FTL context block */
 206+ uint16_t nextcxtpage;
 207+
 208+ /* Seems to be unused */
 209+ uint8_t field_14[4];
 210+
 211+ /* Incremented every time a block erase error leads to a remap,
 212+ but doesn't seem to be read anywhere. */
 213+ uint16_t field_18;
 214+
 215+ /* Number of spare blocks used */
 216+ uint16_t spareused;
 217+
 218+ /* pBlock number of the first spare block */
 219+ uint16_t firstspare;
 220+
 221+ /* Total number of spare blocks */
 222+ uint16_t sparecount;
 223+
 224+ /* Block remap table. Contains the vBlock number the n-th spare
 225+ block is used as a replacement for. 0 = unused, 0xFFFF = bad. */
 226+ uint16_t remaptable[0x334];
 227+
 228+ /* Bad block table. Each bit represents 8 blocks. 1 = OK, 0 = Bad.
 229+ If the entry is zero, you should look at the remap table to see
 230+ if the block is remapped, and if yes, where the replacement is. */
 231+ uint8_t bbt[0x11A];
 232+
 233+ /* pBlock numbers used to store the VFL context. This is a ring
 234+ buffer. On a VFL context write, always 8 pages are written,
 235+ and it passes if at least 4 of them can be read back. */
 236+ uint16_t vflcxtblocks[4];
 237+
 238+ /* Blocks scheduled for remapping are stored at the end of the
 239+ remap table. This is the first index used for them. */
 240+ uint16_t scheduledstart;
 241+
 242+ /* Probably padding */
 243+ uint8_t field_7AC[0x4C];
 244+
 245+ /* First checksum (addition) */
 246+ uint32_t checksum1;
 247+
 248+ /* Second checksum (XOR), there is a bug in whimory regarding this. */
 249+ uint32_t checksum2;
 250+
 251+} __attribute__((packed));
 252+
 253+
 254+/* Layout of the spare bytes of each page on the flash */
 255+union ftl_spare_data_type
 256+{
 257+
 258+ /* The layout used for actual user data (types 0x40 and 0x41) */
 259+ struct ftl_spare_data_user_type
 260+ {
 261+
 262+ /* The lPage, i.e. Sector, number */
 263+ uint32_t lpn;
 264+
 265+ /* The update sequence number of that page,
 266+ copied from ftl_cxt.nextblockusn on write */
 267+ uint32_t usn;
 268+
 269+ /* Seems to be unused */
 270+ uint8_t field_8;
 271+
 272+ /* Type field, 0x40 (data page) or 0x41 (last data page of block) */
 273+ uint8_t type;
 274+
 275+ /* ECC mark, usually 0xFF. If an error occurred while reading the
 276+ page during a copying operation earlier, this will be 0x55. */
 277+ uint8_t eccmark;
 278+
 279+ /* Seems to be unused */
 280+ uint8_t field_B;
 281+
 282+ /* ECC data for the user data */
 283+ uint8_t dataecc[0x28];
 284+
 285+ /* ECC data for the first 0xC bytes above */
 286+ uint8_t spareecc[0xC];
 287+
 288+ } __attribute__((packed)) user;
 289+
 290+ /* The layout used for meta data (other types) */
 291+ struct ftl_spare_data_meta_type
 292+ {
 293+
 294+ /* ftl_cxt.usn for FTL stuff, ftl_vfl_cxt.updatecount for VFL stuff */
 295+ uint32_t usn;
 296+
 297+ /* Index of the thing inside the page,
 298+ for example number / index of the map or erase counter page */
 299+ uint16_t idx;
 300+
 301+ /* Seems to be unused */
 302+ uint8_t field_6;
 303+
 304+ /* Seems to be unused */
 305+ uint8_t field_7;
 306+
 307+ /* Seems to be unused */
 308+ uint8_t field_8;
 309+
 310+ /* Type field:
 311+ 0x43: FTL context page
 312+ 0x44: Block map page
 313+ 0x46: Erase counter page
 314+ 0x47: "FTL is currently mounted", i.e. unclean shutdown, mark
 315+ 0x80: VFL context page */
 316+ uint8_t type;
 317+
 318+ /* ECC mark, usually 0xFF. If an error occurred while reading the
 319+ page during a copying operation earlier, this will be 0x55. */
 320+ uint8_t eccmark;
 321+
 322+ /* Seems to be unused */
 323+ uint8_t field_B;
 324+
 325+ /* ECC data for the user data */
 326+ uint8_t dataecc[0x28];
 327+
 328+ /* ECC data for the first 0xC bytes above */
 329+ uint8_t spareecc[0xC];
 330+
 331+ } __attribute__((packed)) meta;
 332+
 333+};
 334+
 335+
 336+/* Keeps track of troublesome blocks, only in memory, lost on unmount. */
 337+struct ftl_trouble_type
 338+{
 339+
 340+ /* vBlock number of the block giving trouble */
 341+ uint16_t block;
 342+
 343+ /* Bank of the block giving trouble */
 344+ uint8_t bank;
 345+
 346+ /* Error counter, incremented by 3 on error, decremented by 1 on erase,
 347+ remaping will be done when it reaches 6. */
 348+ uint8_t errors;
 349+
 350+} __attribute__((packed));
 351+
 352+
 353+
 354+/* Pointer to an info structure regarding the flash type used */
 355+const struct nand_device_info_type* ftl_nand_type;
 356+
 357+/* Number of banks we detected a chip on */
 358+uint32_t ftl_banks;
 359+
 360+/* Block map, used vor pBlock to vBlock mapping */
 361+uint16_t ftl_map[0x2000];
 362+
 363+/* VFL context for each bank */
 364+struct ftl_vfl_cxt_type ftl_vfl_cxt[4];
 365+
 366+/* FTL context */
 367+struct ftl_cxt_type ftl_cxt;
 368+
 369+/* Temporary data buffers for internal use by the FTL */
 370+uint8_t ftl_buffer[0x800] __attribute__((aligned(16)));
 371+
 372+/* Temporary spare byte buffer for internal use by the FTL */
 373+union ftl_spare_data_type ftl_sparebuffer __attribute__((aligned(16)));
 374+
 375+uint32_t ftl_initialized;
 376+
 377+
 378+#ifndef FTL_READONLY
 379+
 380+/* Lowlevel BBT for each bank */
 381+uint8_t ftl_bbt[4][0x410];
 382+
 383+/* Erase countes for the vBlocks */
 384+uint16_t ftl_erasectr[0x2000];
 385+
 386+/* Used by ftl_log */
 387+uint16_t ftl_offsets[0x11][0x200];
 388+
 389+/* Structs keeping record of scattered page blocks */
 390+struct ftl_log_type ftl_log[0x11];
 391+
 392+/* Global cross-bank update sequence number of the VFL context */
 393+uint32_t ftl_vfl_usn;
 394+
 395+/* Keeps track (temporarily) of troublesome blocks */
 396+struct ftl_trouble_type ftl_troublelog[5];
 397+
 398+/* Counts erase counter page changes, after 100 of them the affected
 399+ page will be committed to the flash. */
 400+uint8_t ftl_erasectr_dirt[8];
 401+
 402+/* Buffer needed for copying pages around while moving or committing blocks.
 403+ This can't be shared with ftl_buffer, because this one could be overwritten
 404+ during the copying operation in order to e.g. commit a CXT. */
 405+uint8_t ftl_copybuffer[0x800] __attribute__((aligned(16)));
 406+
 407+/* Needed to store the old scattered page offsets in order to be able to roll
 408+ back if something fails while compacting a scattered page block. */
 409+uint16_t ftl_offsets_backup[0x200] __attribute__((aligned(16)));
 410+
 411+#endif
 412+
 413+
 414+
 415+
 416+
 417+/* Finds a device info page for the specified bank and returns its number.
 418+ Used to check if one is present, and to read the lowlevel BBT. */
 419+uint32_t ftl_find_devinfo(uint32_t bank)
 420+{
 421+ /* Scan the last 10% of the flash for device info pages */
 422+ uint32_t lowestBlock = (*ftl_nand_type).blocks
 423+ - ((*ftl_nand_type).blocks / 10);
 424+ uint32_t block, page, pagenum;
 425+ for (block = (*ftl_nand_type).blocks - 1; block >= lowestBlock; block--)
 426+ {
 427+ page = (*ftl_nand_type).pagesperblock - 8;
 428+ for (; page < (*ftl_nand_type).pagesperblock; page++)
 429+ {
 430+ pagenum = block * (*ftl_nand_type).pagesperblock + page;
 431+ if ((nand_read_page(bank, pagenum, ftl_buffer,
 432+ &ftl_sparebuffer, 1, 0) & 0x11F) != 0)
 433+ continue;
 434+ if (memcmp(ftl_buffer, "DEVICEINFOSIGN\0", 0x10) == 0)
 435+ return pagenum;
 436+ }
 437+ }
 438+ return 0;
 439+}
 440+
 441+
 442+/* Checks if all banks have proper device info pages */
 443+uint32_t ftl_has_devinfo(void)
 444+{
 445+ uint32_t i;
 446+ for (i = 0; i < ftl_banks; i++) if (ftl_find_devinfo(i) == 0) return 0;
 447+ return 1;
 448+}
 449+
 450+
 451+/* Loads the lowlevel BBT for a bank to the specified buffer.
 452+ This is based on some cryptic disassembly and not fully understood yet. */
 453+uint32_t ftl_load_bbt(uint32_t bank, uint8_t* bbt)
 454+{
 455+ uint32_t i, j;
 456+ uint32_t pagebase, page = ftl_find_devinfo(bank), page2;
 457+ uint32_t unk1, unk2, unk3;
 458+ if (page == 0) return 1;
 459+ pagebase = page & ~((*ftl_nand_type).pagesperblock - 1);
 460+ if ((nand_read_page(bank, page, ftl_buffer,
 461+ (uint32_t*)0, 1, 0) & 0x11F) != 0) return 1;
 462+ if (memcmp(&ftl_buffer[0x18], "BBT", 4) != 0) return 1;
 463+ unk1 = ((uint16_t*)ftl_buffer)[0x10];
 464+ unk2 = ((uint16_t*)ftl_buffer)[0x11];
 465+ unk3 = ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 0xC + 10]
 466+ + ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 0xC + 11];
 467+ for (i = 0; i < unk1; i++)
 468+ {
 469+ for (j = 0; ; j++)
 470+ {
 471+ page2 = unk2 + i + unk3 * j;
 472+ if (page2 >= (uint32_t)((*ftl_nand_type).pagesperblock - 8))
 473+ break;
 474+ if ((nand_read_page(bank, pagebase + page2, ftl_buffer,
 475+ (void*)0, 1, 0) & 0x11F) == 0)
 476+ {
 477+ memcpy(bbt, ftl_buffer, 0x410);
 478+ return 0;
 479+ }
 480+ }
 481+ }
 482+ return 1;
 483+}
 484+
 485+
 486+/* Calculates the checksums for the VFL context page of the specified bank */
 487+void ftl_vfl_calculate_checksum(uint32_t bank,
 488+ uint32_t* checksum1, uint32_t* checksum2)
 489+{
 490+ uint32_t i;
 491+ *checksum1 = 0xAABBCCDD;
 492+ *checksum2 = 0xAABBCCDD;
 493+ for (i = 0; i < 0x1FE; i++)
 494+ {
 495+ *checksum1 += ((uint32_t*)(&ftl_vfl_cxt[bank]))[i];
 496+ *checksum2 ^= ((uint32_t*)(&ftl_vfl_cxt[bank]))[i];
 497+ }
 498+}
 499+
 500+
 501+/* Checks if the checksums of the VFL context
 502+ of the specified bank are correct */
 503+uint32_t ftl_vfl_verify_checksum(uint32_t bank)
 504+{
 505+ uint32_t checksum1, checksum2;
 506+ ftl_vfl_calculate_checksum(bank, &checksum1, &checksum2);
 507+ if (checksum1 == ftl_vfl_cxt[bank].checksum1) return 0;
 508+ /* The following line is pretty obviously a bug in Whimory,
 509+ but we do it the same way for compatibility. */
 510+ if (checksum2 != ftl_vfl_cxt[bank].checksum2) return 0;
 511+ return 1;
 512+}
 513+
 514+
 515+#ifndef FTL_READONLY
 516+/* Updates the checksums of the VFL context of the specified bank */
 517+void ftl_vfl_update_checksum(uint32_t bank)
 518+{
 519+ ftl_vfl_calculate_checksum(bank, &ftl_vfl_cxt[bank].checksum1,
 520+ &ftl_vfl_cxt[bank].checksum2);
 521+}
 522+#endif
 523+
 524+
 525+#ifndef FTL_READONLY
 526+/* Writes 8 copies of the VFL context of the specified bank to flash,
 527+ and succeeds if at least 4 can be read back properly. */
 528+uint32_t ftl_vfl_store_cxt(uint32_t bank)
 529+{
 530+ uint32_t i;
 531+ ftl_vfl_cxt[bank].updatecount--;
 532+ ftl_vfl_cxt[bank].usn = ++ftl_vfl_usn;
 533+ ftl_vfl_cxt[bank].nextcxtpage += 8;
 534+ ftl_vfl_update_checksum(bank);
 535+ memset(&ftl_sparebuffer, 0xFF, 0x40);
 536+ ftl_sparebuffer.meta.usn = ftl_vfl_cxt[bank].updatecount;
 537+ ftl_sparebuffer.meta.field_8 = 0;
 538+ ftl_sparebuffer.meta.type = 0x80;
 539+ for (i = 1; i <= 8; i++)
 540+ {
 541+ uint32_t index = ftl_vfl_cxt[bank].activecxtblock;
 542+ uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index];
 543+ uint32_t page = block * (*ftl_nand_type).pagesperblock;
 544+ page += ftl_vfl_cxt[bank].nextcxtpage - i;
 545+ nand_write_page(bank, page, &ftl_vfl_cxt[bank], &ftl_sparebuffer, 1);
 546+ }
 547+ uint32_t good = 0;
 548+ for (i = 0; i < 8; i++)
 549+ {
 550+ uint32_t index = ftl_vfl_cxt[bank].activecxtblock;
 551+ uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index];
 552+ uint32_t page = block * (*ftl_nand_type).pagesperblock;
 553+ page += ftl_vfl_cxt[bank].nextcxtpage - i;
 554+ if ((nand_read_page(bank, page, ftl_buffer,
 555+ &ftl_sparebuffer, 1, 0) & 0x11F) != 0)
 556+ continue;
 557+ if (memcmp(ftl_buffer, &ftl_vfl_cxt[bank], 0x7AC) != 0)
 558+ continue;
 559+ if (ftl_sparebuffer.meta.usn != ftl_vfl_cxt[bank].updatecount)
 560+ continue;
 561+ if (ftl_sparebuffer.meta.field_8 == 0
 562+ && ftl_sparebuffer.meta.type == 0x80) good++;
 563+ }
 564+ return good > 3 ? 0 : 1;
 565+}
 566+#endif
 567+
 568+
 569+#ifndef FTL_READONLY
 570+/* Commits the VFL context of the specified bank to flash,
 571+ retries until it works or all available pages have been tried */
 572+uint32_t ftl_vfl_commit_cxt(uint32_t bank)
 573+{
 574+ if (ftl_vfl_cxt[bank].nextcxtpage + 8 <= (*ftl_nand_type).pagesperblock)
 575+ if (ftl_vfl_store_cxt(bank) == 0) return 0;
 576+ uint32_t current = ftl_vfl_cxt[bank].activecxtblock;
 577+ uint32_t i = current, j;
 578+ while (1)
 579+ {
 580+ i = (i + 1) & 3;
 581+ if (i == current) break;
 582+ if (ftl_vfl_cxt[bank].vflcxtblocks[i] == 0xFFFF) continue;
 583+ for (j = 0; j < 4; j++)
 584+ if (nand_block_erase(bank, ftl_vfl_cxt[bank].vflcxtblocks[i]
 585+ * (*ftl_nand_type).pagesperblock) == 0)
 586+ break;
 587+ if (j == 4) continue;
 588+ ftl_vfl_cxt[bank].activecxtblock = i;
 589+ ftl_vfl_cxt[bank].nextcxtpage = 0;
 590+ if (ftl_vfl_store_cxt(bank) == 0) return 0;
 591+ }
 592+ return 1;
 593+}
 594+#endif
 595+
 596+
 597+/* Returns a pointer to the most recently updated VFL context,
 598+ used to find out the current FTL context vBlock numbers
 599+ (planetbeing's "maxthing") */
 600+struct ftl_vfl_cxt_type* ftl_vfl_get_newest_cxt(void)
 601+{
 602+ uint32_t i, maxusn;
 603+ struct ftl_vfl_cxt_type* cxt = (struct ftl_vfl_cxt_type*)0;
 604+ maxusn = 0;
 605+ for (i = 0; i < ftl_banks; i++)
 606+ if (ftl_vfl_cxt[i].usn >= maxusn)
 607+ {
 608+ cxt = &ftl_vfl_cxt[i];
 609+ maxusn = ftl_vfl_cxt[i].usn;
 610+ }
 611+ return cxt;
 612+}
 613+
 614+
 615+/* Checks if the specified pBlock is marked bad in the supplied lowlevel BBT.
 616+ Only used while mounting the VFL. */
 617+uint32_t ftl_is_good_block(uint8_t* bbt, uint32_t block)
 618+{
 619+ if ((bbt[block >> 3] & (1 << (block & 7))) == 0) return 0;
 620+ else return 1;
 621+}
 622+
 623+
 624+/* Checks if the specified vBlock could be remapped */
 625+uint32_t ftl_vfl_is_good_block(uint32_t bank, uint32_t block)
 626+{
 627+ uint8_t bbtentry = ftl_vfl_cxt[bank].bbt[block >> 6];
 628+ if ((bbtentry & (1 << ((7 - (block >> 3)) & 7))) == 0) return 0;
 629+ else return 1;
 630+}
 631+
 632+
 633+#ifndef FTL_READONLY
 634+/* Sets or unsets the bad bit of the specified vBlock
 635+ in the specified bank's VFL context */
 636+void ftl_vfl_set_good_block(uint32_t bank, uint32_t block, uint32_t isgood)
 637+{
 638+ uint8_t bit = (1 << ((7 - (block >> 3)) & 7));
 639+ if (isgood == 1) ftl_vfl_cxt[bank].bbt[block >> 6] |= bit;
 640+ else ftl_vfl_cxt[bank].bbt[block >> 6] &= ~bit;
 641+}
 642+#endif
 643+
 644+
 645+/* Tries to read a VFL context from the specified bank, pBlock and page */
 646+uint32_t ftl_vfl_read_page(uint32_t bank, uint32_t block,
 647+ uint32_t startpage, void* databuffer,
 648+ union ftl_spare_data_type* sparebuffer)
 649+{
 650+ uint32_t i;
 651+ for (i = 0; i < 8; i++)
 652+ {
 653+ uint32_t page = block * (*ftl_nand_type).pagesperblock
 654+ + startpage + i;
 655+ if ((nand_read_page(bank, page, databuffer,
 656+ sparebuffer, 1, 1) & 0x11F) == 0)
 657+ if ((*sparebuffer).meta.field_8 == 0
 658+ && (*sparebuffer).meta.type == 0x80)
 659+ return 0;
 660+ }
 661+ return 1;
 662+}
 663+
 664+
 665+/* Translates a bank and vBlock to a pBlock, following remaps */
 666+uint32_t ftl_vfl_get_physical_block(uint32_t bank, uint32_t block)
 667+{
 668+ if (ftl_vfl_is_good_block(bank, block) == 1) return block;
 669+
 670+ uint32_t spareindex;
 671+ uint32_t spareused = ftl_vfl_cxt[bank].spareused;
 672+ for (spareindex = 0; spareindex < spareused; spareindex++)
 673+ if (ftl_vfl_cxt[bank].remaptable[spareindex] == block)
 674+ return ftl_vfl_cxt[bank].firstspare + spareindex;
 675+ return block;
 676+}
 677+
 678+
 679+#ifndef FTL_READONLY
 680+/* Checks if remapping is scheduled for the specified bank and vBlock */
 681+uint32_t ftl_vfl_check_remap_scheduled(uint32_t bank, uint32_t block)
 682+{
 683+ uint32_t i;
 684+ for (i = 0x333; i > 0 && i > ftl_vfl_cxt[bank].scheduledstart; i--)
 685+ if (ftl_vfl_cxt[bank].remaptable[i] == block) return 1;
 686+ return 0;
 687+}
 688+#endif
 689+
 690+
 691+#ifndef FTL_READONLY
 692+/* Schedules remapping for the specified bank and vBlock */
 693+void ftl_vfl_schedule_block_for_remap(uint32_t bank, uint32_t block)
 694+{
 695+ if (ftl_vfl_check_remap_scheduled(bank, block) == 1) return;
 696+ if (ftl_vfl_cxt[bank].scheduledstart == ftl_vfl_cxt[bank].spareused)
 697+ return;
 698+ ftl_vfl_cxt[bank].remaptable[--ftl_vfl_cxt[bank].scheduledstart] = block;
 699+ ftl_vfl_commit_cxt(bank);
 700+}
 701+#endif
 702+
 703+
 704+#ifndef FTL_READONLY
 705+/* Removes the specified bank and vBlock combination
 706+ from the remap scheduled list */
 707+void ftl_vfl_mark_remap_done(uint32_t bank, uint32_t block)
 708+{
 709+ uint32_t i;
 710+ uint32_t start = ftl_vfl_cxt[bank].scheduledstart;
 711+ uint32_t lastscheduled = ftl_vfl_cxt[bank].remaptable[start];
 712+ for (i = 0x333; i > 0 && i > start; i--)
 713+ if (ftl_vfl_cxt[bank].remaptable[i] == block)
 714+ {
 715+ if (i != start && i != 0x333)
 716+ ftl_vfl_cxt[bank].remaptable[i] = lastscheduled;
 717+ ftl_vfl_cxt[bank].scheduledstart++;
 718+ return;
 719+ }
 720+}
 721+#endif
 722+
 723+
 724+#ifndef FTL_READONLY
 725+/* Logs that there is trouble for the specified vBlock on the specified bank.
 726+ The vBlock will be scheduled for remap
 727+ if there is too much trouble with it. */
 728+void ftl_vfl_log_trouble(uint32_t bank, uint32_t vblock)
 729+{
 730+ uint32_t i;
 731+ for (i = 0; i < 5; i++)
 732+ if (ftl_troublelog[i].block == vblock
 733+ && ftl_troublelog[i].bank == bank)
 734+ {
 735+ ftl_troublelog[i].errors += 3;
 736+ if (ftl_troublelog[i].errors > 5)
 737+ {
 738+ ftl_vfl_schedule_block_for_remap(bank, vblock);
 739+ ftl_troublelog[i].block = 0xFFFF;
 740+ }
 741+ return;
 742+ }
 743+ for (i = 0; i < 5; i++)
 744+ if (ftl_troublelog[i].block == 0xFFFF)
 745+ {
 746+ ftl_troublelog[i].block = vblock;
 747+ ftl_troublelog[i].bank = bank;
 748+ ftl_troublelog[i].errors = 3;
 749+ return;
 750+ }
 751+}
 752+#endif
 753+
 754+
 755+#ifndef FTL_READONLY
 756+/* Logs a successful erase for the specified vBlock on the specified bank */
 757+void ftl_vfl_log_success(uint32_t bank, uint32_t vblock)
 758+{
 759+ uint32_t i;
 760+ for (i = 0; i < 5; i++)
 761+ if (ftl_troublelog[i].block == vblock
 762+ && ftl_troublelog[i].bank == bank)
 763+ {
 764+ if (--ftl_troublelog[i].errors == 0)
 765+ ftl_troublelog[i].block = 0xFFFF;
 766+ return;
 767+ }
 768+}
 769+#endif
 770+
 771+
 772+#ifndef FTL_READONLY
 773+/* Tries to remap the specified vBlock on the specified bank,
 774+ not caring about data in there.
 775+ If it worked, it will return the new pBlock number,
 776+ if not (no more spare blocks available), it will return zero. */
 777+uint32_t ftl_vfl_remap_block(uint32_t bank, uint32_t block)
 778+{
 779+ uint32_t i;
 780+ uint32_t newblock = 0, newidx;
 781+ if (bank >= ftl_banks || block >= (*ftl_nand_type).blocks) return 0;
 782+ for (i = 0; i < ftl_vfl_cxt[bank].sparecount; i++)
 783+ if (ftl_vfl_cxt[bank].remaptable[i] == 0)
 784+ {
 785+ newblock = ftl_vfl_cxt[bank].firstspare + i;
 786+ newidx = i;
 787+ break;
 788+ }
 789+ if (newblock == 0) return 0;
 790+ for (i = 0; i < 9; i++)
 791+ if (nand_block_erase(bank,
 792+ newblock * (*ftl_nand_type).pagesperblock) == 0)
 793+ break;
 794+ for (i = 0; i < newidx; i++)
 795+ if (ftl_vfl_cxt[bank].remaptable[i] == block)
 796+ ftl_vfl_cxt[bank].remaptable[i] = 0xFFFF;
 797+ ftl_vfl_cxt[bank].remaptable[newidx] = block;
 798+ ftl_vfl_cxt[bank].spareused++;
 799+ ftl_vfl_set_good_block(bank, block, 0);
 800+ return newblock;
 801+}
 802+#endif
 803+
 804+
 805+// Reads the specified vPage, dealing with all kinds of trouble
 806+uint32_t ftl_vfl_read(uint32_t vpage, void* buffer, void* sparebuffer,
 807+ uint32_t checkempty, uint32_t remaponfail)
 808+{
 809+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 810+ uint32_t syshyperblocks = (*ftl_nand_type).blocks
 811+ - (*ftl_nand_type).userblocks - 0x17;
 812+ uint32_t abspage = vpage + ppb * syshyperblocks;
 813+ if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb)
 814+ {
 815+ return 4;
 816+ }
 817+
 818+ uint32_t bank = abspage % ftl_banks;
 819+ uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks);
 820+ uint32_t page = (abspage / ftl_banks) % (*ftl_nand_type).pagesperblock;
 821+ uint32_t physblock = ftl_vfl_get_physical_block(bank, block);
 822+ uint32_t physpage = physblock * (*ftl_nand_type).pagesperblock + page;
 823+
 824+ uint32_t ret = nand_read_page(bank, physpage, buffer,
 825+ sparebuffer, 1, checkempty);
 826+
 827+ if ((ret & 0x11D) != 0 && (ret & 2) == 0)
 828+ {
 829+ nand_reset(bank);
 830+ ret = nand_read_page(bank, physpage, buffer,
 831+ sparebuffer, 1, checkempty);
 832+#ifdef FTL_READONLY
 833+ (void)remaponfail;
 834+#else
 835+ if (remaponfail == 1 &&(ret & 0x11D) != 0 && (ret & 2) == 0)
 836+ {
 837+ ftl_vfl_schedule_block_for_remap(bank, block);
 838+ }
 839+#endif
 840+ return ret;
 841+ }
 842+
 843+ return ret;
 844+}
 845+
 846+
 847+#ifndef FTL_READONLY
 848+/* Writes the specified vPage, dealing with all kinds of trouble */
 849+uint32_t ftl_vfl_write(uint32_t vpage, void* buffer, void* sparebuffer)
 850+{
 851+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 852+ uint32_t syshyperblocks = (*ftl_nand_type).blocks
 853+ - (*ftl_nand_type).userblocks - 0x17;
 854+ uint32_t abspage = vpage + ppb * syshyperblocks;
 855+ if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb)
 856+ {
 857+ return 4;
 858+ }
 859+
 860+ uint32_t bank = abspage % ftl_banks;
 861+ uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks);
 862+ uint32_t page = (abspage / ftl_banks) % (*ftl_nand_type).pagesperblock;
 863+ uint32_t physblock = ftl_vfl_get_physical_block(bank, block);
 864+ uint32_t physpage = physblock * (*ftl_nand_type).pagesperblock + page;
 865+
 866+ if (nand_write_page(bank, physpage, buffer, sparebuffer, 1) == 0)
 867+ return 0;
 868+ if ((nand_read_page(bank, physpage, ftl_buffer,
 869+ &ftl_sparebuffer, 1, 1) & 0x11F) == 0)
 870+ return 0;
 871+ ftl_vfl_log_trouble(bank, block);
 872+ return 1;
 873+}
 874+#endif
 875+
 876+
 877+/* Mounts the VFL on all banks */
 878+uint32_t ftl_vfl_open(void)
 879+{
 880+ uint32_t i, j, k;
 881+ uint32_t minusn, vflcxtidx, last;
 882+ struct ftl_vfl_cxt_type* cxt;
 883+ uint16_t vflcxtblock[4];
 884+#ifndef FTL_READONLY
 885+ ftl_vfl_usn = 0;
 886+#else
 887+ /* Temporary BBT buffer if we're readonly,
 888+ as we won't need it again after mounting */
 889+ uint8_t bbt[0x410];
 890+#endif
 891+
 892+ uint32_t syshyperblocks = (*ftl_nand_type).blocks
 893+ - (*ftl_nand_type).userblocks - 0x18;
 894+
 895+ for (i = 0; i < ftl_banks; i++)
 896+#ifndef FTL_READONLY
 897+ if (ftl_load_bbt(i, ftl_bbt[i]) == 0)
 898+#else
 899+ if (ftl_load_bbt(i, bbt) == 0)
 900+#endif
 901+ {
 902+ for (j = 1; j <= syshyperblocks; j++)
 903+#ifndef FTL_READONLY
 904+ if (ftl_is_good_block(ftl_bbt[i], j) != 0)
 905+#else
 906+ if (ftl_is_good_block(bbt, j) != 0)
 907+#endif
 908+ if (ftl_vfl_read_page(i, j, 0, ftl_buffer,
 909+ &ftl_sparebuffer) == 0)
 910+ {
 911+ struct ftl_vfl_cxt_type* cxt;
 912+ cxt = (struct ftl_vfl_cxt_type*)ftl_buffer;
 913+ memcpy(vflcxtblock, &(*cxt).vflcxtblocks, 8);
 914+ minusn = 0xFFFFFFFF;
 915+ vflcxtidx = 4;
 916+ for (k = 0; k < 4; k++)
 917+ if (vflcxtblock[k] != 0xFFFF)
 918+ if (ftl_vfl_read_page(i, vflcxtblock[k], 0,
 919+ ftl_buffer,
 920+ &ftl_sparebuffer) == 0)
 921+ if (ftl_sparebuffer.meta.usn > 0
 922+ && ftl_sparebuffer.meta.usn <= minusn)
 923+ {
 924+ minusn = ftl_sparebuffer.meta.usn;
 925+ vflcxtidx = k;
 926+ }
 927+ if (vflcxtidx == 4) return 1;
 928+ last = 0;
 929+ uint32_t max = (*ftl_nand_type).pagesperblock;
 930+ for (k = 8; k < max; k += 8)
 931+ {
 932+ if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx],
 933+ k, ftl_buffer,
 934+ &ftl_sparebuffer) != 0)
 935+ break;
 936+ last = k;
 937+ }
 938+ if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx],
 939+ last, ftl_buffer,
 940+ &ftl_sparebuffer) != 0)
 941+ return 1;
 942+ memcpy(&ftl_vfl_cxt[i], ftl_buffer, 0x800);
 943+ if (ftl_vfl_verify_checksum(i) != 0) return 1;
 944+#ifndef FTL_READONLY
 945+ if (ftl_vfl_usn < ftl_vfl_cxt[i].usn)
 946+ ftl_vfl_usn = ftl_vfl_cxt[i].usn;
 947+#endif
 948+ break;
 949+ }
 950+ }
 951+ else
 952+ {
 953+ return 1;
 954+ }
 955+ cxt = ftl_vfl_get_newest_cxt();
 956+ for (i = 0; i < ftl_banks; i++)
 957+ memcpy(ftl_vfl_cxt[i].ftlctrlblocks, (*cxt).ftlctrlblocks, 6);
 958+ return 0;
 959+}
 960+
 961+
 962+/* Mounts the actual FTL */
 963+uint32_t ftl_open(void)
 964+{
 965+ uint32_t i;
 966+ uint32_t ret;
 967+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 968+ struct ftl_vfl_cxt_type* cxt = ftl_vfl_get_newest_cxt();
 969+
 970+ uint32_t ftlcxtblock = 0xffffffff;
 971+ uint32_t minlpn = 0xffffffff;
 972+ for (i = 0; i < 3; i++)
 973+ {
 974+ ret = ftl_vfl_read(ppb * (*cxt).ftlctrlblocks[i],
 975+ ftl_buffer, &ftl_sparebuffer, 1, 0);
 976+ if ((ret &= 0x11F) != 0) continue;
 977+ if (ftl_sparebuffer.user.type - 0x43 > 4) continue;
 978+ if (ftlcxtblock != 0xffffffff && ftl_sparebuffer.user.lpn >= minlpn)
 979+ continue;
 980+ minlpn = ftl_sparebuffer.user.lpn;
 981+ ftlcxtblock = (*cxt).ftlctrlblocks[i];
 982+ }
 983+
 984+ if (ftlcxtblock == 0xffffffff) return 1;
 985+
 986+ uint32_t ftlcxtfound = 0;
 987+ for (i = (*ftl_nand_type).pagesperblock * ftl_banks - 1; i > 0; i--)
 988+ {
 989+ ret = ftl_vfl_read(ppb * ftlcxtblock + i,
 990+ ftl_buffer, &ftl_sparebuffer, 1, 0);
 991+ if ((ret & 0x11F) != 0) continue;
 992+ else if (ftl_sparebuffer.user.type == 0x43)
 993+ {
 994+ memcpy(&ftl_cxt, ftl_buffer, 0x28C);
 995+ ftlcxtfound = 1;
 996+ break;
 997+ }
 998+ else
 999+ {
 1000+ // This will trip if there was an unclean unmount before.
 1001+#ifndef FTL_FORCEMOUNT
 1002+ break;
 1003+#endif
 1004+ }
 1005+ }
 1006+
 1007+ if (ftlcxtfound == 0) return 1;
 1008+
 1009+ uint32_t pagestoread = (*ftl_nand_type).userblocks >> 10;
 1010+ if (((*ftl_nand_type).userblocks & 0x1FF) != 0) pagestoread++;
 1011+
 1012+ for (i = 0; i < pagestoread; i++)
 1013+ {
 1014+ if ((ftl_vfl_read(ftl_cxt.ftl_map_pages[i],
 1015+ ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
 1016+ return 1;
 1017+
 1018+ uint32_t toread = 2048;
 1019+ if (toread > ((*ftl_nand_type).userblocks << 1) - (i << 11))
 1020+ toread = ((*ftl_nand_type).userblocks << 1) - (i << 11);
 1021+
 1022+ memcpy(&ftl_map[i << 10], ftl_buffer, toread);
 1023+ }
 1024+
 1025+#ifndef FTL_READONLY
 1026+ pagestoread = ((*ftl_nand_type).userblocks + 23) >> 10;
 1027+ if ((((*ftl_nand_type).userblocks + 23) & 0x1FF) != 0) pagestoread++;
 1028+
 1029+ for (i = 0; i < pagestoread; i++)
 1030+ {
 1031+ if ((ftl_vfl_read(ftl_cxt.ftl_erasectr_pages[i],
 1032+ ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
 1033+ return 1;
 1034+
 1035+ uint32_t toread = 2048;
 1036+ if (toread > (((*ftl_nand_type).userblocks + 23) << 1) - (i << 11))
 1037+ toread = (((*ftl_nand_type).userblocks + 23) << 1) - (i << 11);
 1038+
 1039+ memcpy(&ftl_erasectr[i << 10], ftl_buffer, toread);
 1040+ }
 1041+
 1042+ for (i = 0; i < 0x11; i++)
 1043+ {
 1044+ ftl_log[i].scatteredvblock = 0xFFFF;
 1045+ ftl_log[i].logicalvblock = 0xFFFF;
 1046+ ftl_log[i].pageoffsets = ftl_offsets[i];
 1047+ }
 1048+
 1049+ memset(ftl_troublelog, 0xFF, 20);
 1050+ memset(ftl_erasectr_dirt, 0, 8);
 1051+#endif
 1052+
 1053+ return 0;
 1054+}
 1055+
 1056+
 1057+#ifndef FTL_READONLY
 1058+/* Returns a pointer to the ftl_log entry for the specified vBlock,
 1059+ or null, if there is none */
 1060+struct ftl_log_type* ftl_get_log_entry(uint32_t block)
 1061+{
 1062+ uint32_t i;
 1063+ for (i = 0; i < 0x11; i++)
 1064+ {
 1065+ if (ftl_log[i].scatteredvblock == 0xFFFF) continue;
 1066+ if (ftl_log[i].logicalvblock == block) return &ftl_log[i];
 1067+ }
 1068+ return (struct ftl_log_type*)0;
 1069+}
 1070+#endif
 1071+
 1072+/* Exposed function: Read highlevel sectors */
 1073+uint32_t storage_read(uint32_t sector, uint32_t count, void* buffer)
 1074+{
 1075+ uint32_t i;
 1076+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 1077+ uint32_t error = 0;
 1078+
 1079+ if (sector + count > (*ftl_nand_type).userblocks * ppb)
 1080+ return 1;
 1081+ if (count == 0) return 0;
 1082+
 1083+ for (i = 0; i < count; i++)
 1084+ {
 1085+ uint32_t block = (sector + i) / ppb;
 1086+ uint32_t page = (sector + i) % ppb;
 1087+
 1088+ uint32_t abspage = ftl_map[block] * ppb + page;
 1089+#ifndef FTL_READONLY
 1090+ struct ftl_log_type* logentry = ftl_get_log_entry(block);
 1091+ if (logentry != (struct ftl_log_type*)0)
 1092+ {
 1093+ if ((*logentry).scatteredvblock != 0xFFFF
 1094+ && (*logentry).pageoffsets[page] != 0xFFFF)
 1095+ {
 1096+ abspage = (*logentry).scatteredvblock * ppb
 1097+ + (*logentry).pageoffsets[page];
 1098+ }
 1099+ }
 1100+#endif
 1101+
 1102+ uint32_t ret = ftl_vfl_read(abspage, &((uint8_t*)buffer)[i << 11],
 1103+ &ftl_sparebuffer, 1, 1);
 1104+ if ((ret & 2) != 0) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
 1105+ else if ((ret & 0x11D) != 0 || ftl_sparebuffer.user.eccmark != 0xFF)
 1106+ {
 1107+ error = 1;
 1108+ memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
 1109+ }
 1110+ }
 1111+ return error;
 1112+}
 1113+
 1114+
 1115+#ifndef FTL_READONLY
 1116+/* Performs a vBlock erase, dealing with hardware,
 1117+ remapping and all kinds of trouble */
 1118+uint32_t ftl_erase_block_internal(uint32_t block)
 1119+{
 1120+ uint32_t i, j;
 1121+ block = block + (*ftl_nand_type).blocks
 1122+ - (*ftl_nand_type).userblocks - 0x17;
 1123+ if (block == 0 || block >= (*ftl_nand_type).blocks) return 1;
 1124+ for (i = 0; i < ftl_banks; i++)
 1125+ {
 1126+ if (ftl_vfl_check_remap_scheduled(i, block) == 1)
 1127+ {
 1128+ ftl_vfl_remap_block(i, block);
 1129+ ftl_vfl_mark_remap_done(i, block);
 1130+ }
 1131+ ftl_vfl_log_success(i, block);
 1132+ uint32_t pblock = ftl_vfl_get_physical_block(i, block);
 1133+ uint32_t rc;
 1134+ for (j = 0; j < 3; j++)
 1135+ {
 1136+ rc = nand_block_erase(i, pblock * (*ftl_nand_type).pagesperblock);
 1137+ if (rc == 0) break;
 1138+ }
 1139+ if (rc != 0)
 1140+ {
 1141+ if (pblock != block)
 1142+ {
 1143+ uint32_t spareindex = pblock - ftl_vfl_cxt[i].firstspare;
 1144+ ftl_vfl_cxt[i].remaptable[spareindex] = 0xFFFF;
 1145+ }
 1146+ ftl_vfl_cxt[i].field_18++;
 1147+ if (ftl_vfl_remap_block(i, block) == 0) return 1;
 1148+ if (ftl_vfl_commit_cxt(i) != 0) return 1;
 1149+ memset(&ftl_sparebuffer, 0, 0x40);
 1150+ nand_write_page(i, pblock, &ftl_vfl_cxt[0], &ftl_sparebuffer, 1);
 1151+ }
 1152+ }
 1153+ return 0;
 1154+}
 1155+#endif
 1156+
 1157+
 1158+#ifndef FTL_READONLY
 1159+/* Highlevel vBlock erase, that increments the erase counter for the block */
 1160+uint32_t ftl_erase_block(uint32_t block)
 1161+{
 1162+ ftl_erasectr[block]++;
 1163+ if (ftl_erasectr_dirt[block >> 10] == 100) ftl_cxt.erasedirty = 1;
 1164+ else ftl_erasectr_dirt[block >> 10]++;
 1165+ return ftl_erase_block_internal(block);
 1166+}
 1167+#endif
 1168+
 1169+
 1170+#ifndef FTL_READONLY
 1171+/* Allocates a block from the pool,
 1172+ returning its vBlock number, or 0xFFFFFFFF on error */
 1173+uint32_t ftl_allocate_pool_block(void)
 1174+{
 1175+ uint32_t i;
 1176+ uint32_t erasectr = 0xFFFFFFFF, bestidx = 0xFFFFFFFF, block;
 1177+ for (i = 0; i < ftl_cxt.freecount; i++)
 1178+ {
 1179+ uint32_t idx = ftl_cxt.nextfreeidx + i;
 1180+ if (idx >= 0x14) idx -= 0x14;
 1181+ if (!ftl_cxt.blockpool[idx]) continue;
 1182+ if (ftl_erasectr[ftl_cxt.blockpool[idx]] < erasectr)
 1183+ {
 1184+ erasectr = ftl_erasectr[ftl_cxt.blockpool[idx]];
 1185+ bestidx = idx;
 1186+ }
 1187+ }
 1188+ if (bestidx == 0xFFFFFFFF) return 0xFFFFFFFF;
 1189+ block = ftl_cxt.blockpool[bestidx];
 1190+ if (bestidx != ftl_cxt.nextfreeidx)
 1191+ {
 1192+ ftl_cxt.blockpool[bestidx] = ftl_cxt.blockpool[ftl_cxt.nextfreeidx];
 1193+ ftl_cxt.blockpool[ftl_cxt.nextfreeidx] = block;
 1194+ }
 1195+ if (block > (uint32_t)(*ftl_nand_type).userblocks + 0x17) return 0xFFFFFFFF;
 1196+ if (ftl_erase_block(block) != 0) return 0xFFFFFFFF;
 1197+ if (++ftl_cxt.nextfreeidx == 0x14) ftl_cxt.nextfreeidx = 0;
 1198+ ftl_cxt.freecount--;
 1199+ return block;
 1200+}
 1201+#endif
 1202+
 1203+
 1204+#ifndef FTL_READONLY
 1205+/* Releases a vBlock back into the pool */
 1206+void ftl_release_pool_block(uint32_t block)
 1207+{
 1208+ uint32_t idx = ftl_cxt.nextfreeidx + ftl_cxt.freecount++;
 1209+ if (idx >= 0x14) idx -= 0x14;
 1210+ ftl_cxt.blockpool[idx] = block;
 1211+}
 1212+#endif
 1213+
 1214+
 1215+#ifndef FTL_READONLY
 1216+/* Commits the location of the FTL context blocks
 1217+ to a semi-randomly chosen VFL context */
 1218+uint32_t ftl_store_ctrl_block_list(void)
 1219+{
 1220+ uint32_t i;
 1221+ for (i = 0; i < ftl_banks; i++)
 1222+ memcpy(ftl_vfl_cxt[i].ftlctrlblocks, ftl_cxt.ftlctrlblocks, 6);
 1223+ return ftl_vfl_commit_cxt(ftl_vfl_usn % ftl_banks);
 1224+}
 1225+#endif
 1226+
 1227+
 1228+#ifndef FTL_READONLY
 1229+/* Saves the n-th erase counter page to the flash,
 1230+ because it is too dirty or needs to be moved. */
 1231+uint32_t ftl_save_erasectr_page(uint32_t index)
 1232+{
 1233+ memset(&ftl_sparebuffer, 0xFF, 0x40);
 1234+ ftl_sparebuffer.meta.usn = ftl_cxt.usn;
 1235+ ftl_sparebuffer.meta.idx = index;
 1236+ ftl_sparebuffer.meta.type = 0x46;
 1237+ if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_erasectr[index << 10],
 1238+ &ftl_sparebuffer) != 0)
 1239+ return 1;
 1240+ if ((ftl_vfl_read(ftl_cxt.ftlctrlpage, ftl_buffer,
 1241+ &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
 1242+ return 1;
 1243+ if (memcmp(ftl_buffer, &ftl_erasectr[index << 10], 0x800) != 0) return 1;
 1244+ if (ftl_sparebuffer.meta.type != 0x46) return 1;
 1245+ if (ftl_sparebuffer.meta.idx != index) return 1;
 1246+ if (ftl_sparebuffer.meta.usn != ftl_cxt.usn) return 1;
 1247+ ftl_cxt.ftl_erasectr_pages[index] = ftl_cxt.ftlctrlpage;
 1248+ ftl_erasectr_dirt[index] = 0;
 1249+ return 0;
 1250+}
 1251+#endif
 1252+
 1253+
 1254+#ifndef FTL_READONLY
 1255+/* Increments ftl_cxt.ftlctrlpage to the next available FTL context page,
 1256+ allocating a new context block if neccessary. */
 1257+uint32_t ftl_next_ctrl_pool_page(void)
 1258+{
 1259+ uint32_t i;
 1260+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 1261+ if (++ftl_cxt.ftlctrlpage % ppb != 0) return 0;
 1262+ for (i = 0; i < 3; i++)
 1263+ if ((ftl_cxt.ftlctrlblocks[i] + 1) * ppb == ftl_cxt.ftlctrlpage)
 1264+ break;
 1265+ i = (i + 1) % 3;
 1266+ uint32_t oldblock = ftl_cxt.ftlctrlblocks[i];
 1267+ uint32_t newblock = ftl_allocate_pool_block();
 1268+ if (newblock == 0xFFFFFFFF) return 1;
 1269+ ftl_cxt.ftlctrlblocks[i] = newblock;
 1270+ ftl_cxt.ftlctrlpage = newblock * ppb;
 1271+ uint32_t pagestoread = ((*ftl_nand_type).userblocks + 23) >> 10;
 1272+ if ((((*ftl_nand_type).userblocks + 23) & 0x1FF) != 0) pagestoread++;
 1273+ for (i = 0; i < pagestoread; i++)
 1274+ if (oldblock * ppb <= ftl_cxt.ftl_erasectr_pages[i]
 1275+ && (oldblock + 1) * ppb > ftl_cxt.ftl_erasectr_pages[i])
 1276+ {
 1277+ ftl_cxt.usn--;
 1278+ if (ftl_save_erasectr_page(i) != 0)
 1279+ {
 1280+ ftl_cxt.ftlctrlblocks[i] = oldblock;
 1281+ ftl_cxt.ftlctrlpage = oldblock * (ppb + 1) - 1;
 1282+ ftl_release_pool_block(newblock);
 1283+ return 1;
 1284+ }
 1285+ ftl_cxt.ftlctrlpage++;
 1286+ }
 1287+ ftl_release_pool_block(oldblock);
 1288+ return ftl_store_ctrl_block_list();
 1289+}
 1290+#endif
 1291+
 1292+
 1293+#ifndef FTL_READONLY
 1294+/* Copies a vPage from one location to another */
 1295+uint32_t ftl_copy_page(uint32_t source, uint32_t destination,
 1296+ uint32_t lpn, uint32_t type)
 1297+{
 1298+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 1299+ uint32_t rc = ftl_vfl_read(source, ftl_copybuffer,
 1300+ &ftl_sparebuffer, 1, 1) & 0x11F;
 1301+ memset(&ftl_sparebuffer, 0xFF, 0x40);
 1302+ ftl_sparebuffer.user.lpn = lpn;
 1303+ ftl_sparebuffer.user.usn = ++ftl_cxt.nextblockusn;
 1304+ ftl_sparebuffer.user.type = 0x40;
 1305+ if ((rc & 2) != 0) memset(ftl_copybuffer, 0, 0x800);
 1306+ else if (rc != 0) ftl_sparebuffer.user.eccmark = 0x55;
 1307+ if (type == 1 && destination % ppb == ppb - 1)
 1308+ ftl_sparebuffer.user.type = 0x41;
 1309+ return ftl_vfl_write(destination, ftl_copybuffer, &ftl_sparebuffer);
 1310+}
 1311+#endif
 1312+
 1313+
 1314+#ifndef FTL_READONLY
 1315+/* Copies a pBlock to a vBlock */
 1316+uint32_t ftl_copy_block(uint32_t source, uint32_t destination)
 1317+{
 1318+ uint32_t i;
 1319+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 1320+ uint32_t error = 0;
 1321+ ftl_cxt.nextblockusn++;
 1322+ for (i = 0; i < ppb; i++)
 1323+ {
 1324+ uint32_t rc = storage_read(source * ppb + i, 1, ftl_copybuffer);
 1325+ memset(&ftl_sparebuffer, 0xFF, 0x40);
 1326+ ftl_sparebuffer.user.lpn = source * ppb + i;
 1327+ ftl_sparebuffer.user.usn = ftl_cxt.nextblockusn;
 1328+ ftl_sparebuffer.user.type = 0x40;
 1329+ if (rc != 0) ftl_sparebuffer.user.eccmark = 0x55;
 1330+ if (i == ppb - 1) ftl_sparebuffer.user.type = 0x41;
 1331+ if (ftl_vfl_write(destination * ppb + i,
 1332+ ftl_copybuffer, &ftl_sparebuffer) != 0)
 1333+ {
 1334+ error = 1;
 1335+ break;
 1336+ }
 1337+ }
 1338+ if (error != 0)
 1339+ {
 1340+ ftl_erase_block(destination);
 1341+ return 1;
 1342+ }
 1343+ return 0;
 1344+}
 1345+#endif
 1346+
 1347+
 1348+#ifndef FTL_READONLY
 1349+/* Clears ftl_log.issequential, if something violating that is written. */
 1350+void ftl_check_still_sequential(struct ftl_log_type* entry, uint32_t page)
 1351+{
 1352+ if ((*entry).pagesused != (*entry).pagescurrent
 1353+ || (*entry).pageoffsets[page] != page)
 1354+ (*entry).issequential = 0;
 1355+}
 1356+#endif
 1357+
 1358+
 1359+#ifndef FTL_READONLY
 1360+/* Copies all pages that are currently used from the scattered page block in
 1361+ use by the supplied ftl_log entry to a newly-allocated one, and releases
 1362+ the old one.
 1363+ In other words: It kicks the pages containing old garbage out of it to make
 1364+ space again. This is usually done when a scattered page block is being
 1365+ removed because it is full, but less than half of the pages in there are
 1366+ still in use and rest is just filled with old crap. */
 1367+uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
 1368+{
 1369+ uint32_t i, j;
 1370+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 1371+ uint32_t error;
 1372+ struct ftl_log_type backup;
 1373+ if ((*entry).pagescurrent == 0)
 1374+ {
 1375+ ftl_release_pool_block((*entry).scatteredvblock);
 1376+ (*entry).scatteredvblock = 0xFFFF;
 1377+ return 0;
 1378+ }
 1379+ backup = *entry;
 1380+ memcpy(ftl_offsets_backup, (*entry).pageoffsets, 0x400);
 1381+ for (i = 0; i < 4; i++)
 1382+ {
 1383+ uint32_t block = ftl_allocate_pool_block();
 1384+ if (block == 0xFFFFFFFF) return 1;
 1385+ (*entry).pagesused = 0;
 1386+ (*entry).pagescurrent = 0;
 1387+ (*entry).issequential = 1;
 1388+ (*entry).scatteredvblock = block;
 1389+ error = 0;
 1390+ for (j = 0; j < ppb; j++)
 1391+ if ((*entry).pageoffsets[j] != 0xFFFF)
 1392+ {
 1393+ uint32_t lpn = (*entry).logicalvblock * ppb + j;
 1394+ uint32_t newpage = block * ppb + (*entry).pagesused;
 1395+ uint32_t oldpage = backup.scatteredvblock * ppb
 1396+ + (*entry).pageoffsets[j];
 1397+ if (ftl_copy_page(oldpage, newpage, lpn,
 1398+ (*entry).issequential) != 0)
 1399+ {
 1400+ error = 1;
 1401+ break;
 1402+ }
 1403+ (*entry).pageoffsets[j] = (*entry).pagesused++;
 1404+ (*entry).pagescurrent++;
 1405+ ftl_check_still_sequential(entry, j);
 1406+ }
 1407+ if (backup.pagescurrent != (*entry).pagescurrent) error = 1;
 1408+ if (error == 0)
 1409+ {
 1410+ ftl_release_pool_block(backup.scatteredvblock);
 1411+ break;
 1412+ }
 1413+ *entry = backup;
 1414+ memcpy((*entry).pageoffsets, ftl_offsets_backup, 0x400);
 1415+ }
 1416+ return error;
 1417+}
 1418+#endif
 1419+
 1420+
 1421+#ifndef FTL_READONLY
 1422+/* Commits an ftl_log entry to proper blocks, no matter what's in there. */
 1423+uint32_t ftl_commit_scattered(struct ftl_log_type* entry)
 1424+{
 1425+ uint32_t i;
 1426+ uint32_t error;
 1427+ uint32_t block;
 1428+ for (i = 0; i < 4; i++)
 1429+ {
 1430+ block = ftl_allocate_pool_block();
 1431+ if (block == 0xFFFFFFFF) return 1;
 1432+ error = ftl_copy_block((*entry).logicalvblock, block);
 1433+ if (error == 0) break;
 1434+ ftl_release_pool_block(block);
 1435+ }
 1436+ if (error != 0) return 1;
 1437+ ftl_release_pool_block((*entry).scatteredvblock);
 1438+ (*entry).scatteredvblock = 0xFFFF;
 1439+ ftl_release_pool_block(ftl_map[(*entry).logicalvblock]);
 1440+ ftl_map[(*entry).logicalvblock] = block;
 1441+ return 0;
 1442+}
 1443+#endif
 1444+
 1445+
 1446+#ifndef FTL_READONLY
 1447+/* Fills the rest of a scattered page block that was actually written
 1448+ sequentially until now, in order to be able to save a block erase by
 1449+ committing it without needing to copy it again.
 1450+ If this fails for whichever reason, it will be committed the usual way. */
 1451+uint32_t ftl_commit_sequential(struct ftl_log_type* entry)
 1452+{
 1453+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 1454+
 1455+ if ((*entry).issequential != 1
 1456+ || (*entry).pagescurrent != (*entry).pagesused)
 1457+ return 1;
 1458+
 1459+ for (; (*entry).pagesused < ppb; (*entry).pagesused++)
 1460+ {
 1461+ uint32_t lpn = (*entry).logicalvblock * ppb + (*entry).pagesused;
 1462+ uint32_t newpage = (*entry).scatteredvblock * ppb
 1463+ + (*entry).pagesused;
 1464+ uint32_t oldpage = ftl_map[(*entry).logicalvblock] * ppb
 1465+ + (*entry).pagesused;
 1466+ if ((*entry).pageoffsets[(*entry).pagesused] != 0xFFFF
 1467+ || ftl_copy_page(oldpage, newpage, lpn, 1) != 0)
 1468+ return ftl_commit_scattered(entry);
 1469+ }
 1470+ ftl_release_pool_block(ftl_map[(*entry).logicalvblock]);
 1471+ ftl_map[(*entry).logicalvblock] = (*entry).scatteredvblock;
 1472+ (*entry).scatteredvblock = 0xFFFF;
 1473+ return 0;
 1474+}
 1475+#endif
 1476+
 1477+
 1478+#ifndef FTL_READONLY
 1479+/* If a log entry is supplied, its scattered page block will be removed in
 1480+ whatever way seems most appropriate. Else, the oldest scattered page block
 1481+ will be freed by committing it. */
 1482+uint32_t ftl_remove_scattered_block(struct ftl_log_type* entry)
 1483+{
 1484+ uint32_t i;
 1485+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 1486+ uint32_t age = 0xFFFFFFFF, used = 0;
 1487+ if (entry == (struct ftl_log_type*)0)
 1488+ {
 1489+ for (i = 0; i < 0x11; i++)
 1490+ {
 1491+ if (ftl_log[i].scatteredvblock == 0xFFFF) continue;
 1492+ if (ftl_log[i].pagesused == 0 || ftl_log[i].pagescurrent == 0)
 1493+ return 1;
 1494+ if (ftl_log[i].usn < age
 1495+ || (ftl_log[i].usn == age && ftl_log[i].pagescurrent > used))
 1496+ {
 1497+ age = ftl_log[i].usn;
 1498+ used = ftl_log[i].pagescurrent;
 1499+ entry = &ftl_log[i];
 1500+ }
 1501+ }
 1502+ if (entry == (struct ftl_log_type*)0) return 1;
 1503+ }
 1504+ else if ((*entry).pagescurrent < ppb / 2)
 1505+ {
 1506+ ftl_cxt.swapcounter++;
 1507+ return ftl_compact_scattered(entry);
 1508+ }
 1509+ ftl_cxt.swapcounter++;
 1510+ if ((*entry).issequential == 1) return ftl_commit_sequential(entry);
 1511+ else return ftl_commit_scattered(entry);
 1512+}
 1513+#endif
 1514+
 1515+
 1516+#ifndef FTL_READONLY
 1517+/* Initialize a log entry to the values for an empty scattered page block */
 1518+void ftl_init_log_entry(struct ftl_log_type* entry)
 1519+{
 1520+ (*entry).issequential = 1;
 1521+ (*entry).pagescurrent = 0;
 1522+ (*entry).pagesused = 0;
 1523+ memset((*entry).pageoffsets, 0xFF, 0x400);
 1524+}
 1525+#endif
 1526+
 1527+
 1528+#ifndef FTL_READONLY
 1529+/* Allocates a log entry for the specified vBlock,
 1530+ first making space, if neccessary. */
 1531+struct ftl_log_type* ftl_allocate_log_entry(uint32_t block)
 1532+{
 1533+ uint32_t i;
 1534+ struct ftl_log_type* entry = ftl_get_log_entry(block);
 1535+ if (entry != (struct ftl_log_type*)0) return entry;
 1536+
 1537+ for (i = 0; i < 0x11; i++)
 1538+ {
 1539+ if (ftl_log[i].scatteredvblock == 0xFFFF) continue;
 1540+ if (ftl_log[i].pagesused == 0)
 1541+ {
 1542+ entry = &ftl_log[i];
 1543+ break;
 1544+ }
 1545+ }
 1546+
 1547+ if (entry == (struct ftl_log_type*)0)
 1548+ {
 1549+ if (ftl_cxt.freecount <= 3)
 1550+ if (ftl_remove_scattered_block((struct ftl_log_type*)0) != 0)
 1551+ return (struct ftl_log_type*)0;
 1552+ entry = ftl_log;
 1553+ while ((*entry).scatteredvblock != 0xFFFF) entry = &entry[1];
 1554+ (*entry).scatteredvblock = ftl_allocate_pool_block();
 1555+ if ((*entry).scatteredvblock == 0xFFFF)
 1556+ {
 1557+ (*entry).scatteredvblock = 0xFFFF;
 1558+ return (struct ftl_log_type*)0;
 1559+ }
 1560+ }
 1561+
 1562+ ftl_init_log_entry(entry);
 1563+ (*entry).logicalvblock = block;
 1564+ (*entry).usn = ftl_cxt.nextblockusn - 1;
 1565+
 1566+ return entry;
 1567+}
 1568+#endif
 1569+
 1570+
 1571+#ifndef FTL_READONLY
 1572+/* Commits the FTL block map, erase counters, and context to flash */
 1573+uint32_t ftl_commit_cxt(void)
 1574+{
 1575+ uint32_t i;
 1576+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 1577+ uint32_t mappages = ((*ftl_nand_type).userblocks + 0x3ff) >> 10;
 1578+ uint32_t ctrpages = ((*ftl_nand_type).userblocks + 23 + 0x3ff) >> 10;
 1579+ uint32_t endpage = ftl_cxt.ftlctrlpage + mappages + ctrpages + 1;
 1580+ if (endpage % ppb > ppb - 1)
 1581+ ftl_cxt.ftlctrlpage |= ppb - 1;
 1582+ for (i = 0; i < ctrpages; i++)
 1583+ {
 1584+ if (ftl_next_ctrl_pool_page() != 0) return 1;
 1585+ if (ftl_save_erasectr_page(i) != 0) return 1;
 1586+ }
 1587+ for (i = 0; i < mappages; i++)
 1588+ {
 1589+ if (ftl_next_ctrl_pool_page() != 0) return 1;
 1590+ memset(&ftl_sparebuffer, 0xFF, 0x40);
 1591+ ftl_sparebuffer.meta.usn = ftl_cxt.usn;
 1592+ ftl_sparebuffer.meta.idx = i;
 1593+ ftl_sparebuffer.meta.type = 0x44;
 1594+ if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_map[i << 10],
 1595+ &ftl_sparebuffer) != 0)
 1596+ return 1;
 1597+ ftl_cxt.ftl_map_pages[i] = ftl_cxt.ftlctrlpage;
 1598+ }
 1599+ if (ftl_next_ctrl_pool_page() != 0) return 1;
 1600+ ftl_cxt.clean_flag = 1;
 1601+ memset(&ftl_sparebuffer, 0xFF, 0x40);
 1602+ ftl_sparebuffer.meta.usn = ftl_cxt.usn;
 1603+ ftl_sparebuffer.meta.type = 0x43;
 1604+ if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_cxt, &ftl_sparebuffer) != 0)
 1605+ return 1;
 1606+ return 0;
 1607+}
 1608+#endif
 1609+
 1610+
 1611+#ifndef FTL_READONLY
 1612+/* Swaps the most and least worn block on the flash,
 1613+ to better distribute wear. It will refuse to do anything
 1614+ if the wear spread is lower than 5 erases. */
 1615+uint32_t ftl_swap_blocks(void)
 1616+{
 1617+ uint32_t i;
 1618+ uint32_t min = 0xFFFFFFFF, max = 0, maxidx = 0x14;
 1619+ uint32_t minidx = 0, minvb = 0, maxvb = 0;
 1620+ for (i = 0; i < ftl_cxt.freecount; i++)
 1621+ {
 1622+ uint32_t idx = ftl_cxt.nextfreeidx + i;
 1623+ if (idx >= 0x14) idx -= 0x14;
 1624+ if (ftl_erasectr[ftl_cxt.blockpool[idx]] > max)
 1625+ {
 1626+ maxidx = idx;
 1627+ maxvb = ftl_cxt.blockpool[idx];
 1628+ max = ftl_erasectr[maxidx];
 1629+ }
 1630+ }
 1631+ if (maxidx == 0x14) return 0;
 1632+ for (i = 0; i < (*ftl_nand_type).userblocks; i++)
 1633+ {
 1634+ if (ftl_erasectr[ftl_map[i]] > max) max = ftl_erasectr[ftl_map[i]];
 1635+ if (ftl_get_log_entry(i) != (struct ftl_log_type*)0) continue;
 1636+ if (ftl_erasectr[ftl_map[i]] < min)
 1637+ {
 1638+ minidx = i;
 1639+ minvb = ftl_map[i];
 1640+ min = ftl_erasectr[minidx];
 1641+ }
 1642+ }
 1643+ if (max - min < 5) return 0;
 1644+ if (minvb == maxvb) return 0;
 1645+ if (ftl_erase_block(maxvb) != 0) return 1;
 1646+ if (ftl_copy_block(minidx, maxvb) != 0) return 1;
 1647+ ftl_cxt.blockpool[maxidx] = minvb;
 1648+ ftl_map[minidx] = maxvb;
 1649+ return 0;
 1650+}
 1651+#endif
 1652+
 1653+
 1654+#ifndef FTL_READONLY
 1655+/* Exposed function: Write highlevel sectors */
 1656+uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer)
 1657+{
 1658+ uint32_t i, j;
 1659+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 1660+
 1661+ if (sector + count > (*ftl_nand_type).userblocks * ppb)
 1662+ return 1;
 1663+
 1664+ if (count == 0) return 0;
 1665+
 1666+ if (ftl_cxt.clean_flag == 1)
 1667+ {
 1668+ for (i = 0; i < 3; i++)
 1669+ {
 1670+ if (ftl_next_ctrl_pool_page() != 0) return 1;
 1671+ memset(ftl_buffer, 0xFF, 0x800);
 1672+ memset(&ftl_sparebuffer, 0xFF, 0x40);
 1673+ ftl_sparebuffer.meta.usn = ftl_cxt.usn;
 1674+ ftl_sparebuffer.meta.type = 0x47;
 1675+ if (ftl_vfl_write(ftl_cxt.ftlctrlpage, ftl_buffer,
 1676+ &ftl_sparebuffer) == 0)
 1677+ break;
 1678+ }
 1679+ if (i == 3) return 1;
 1680+ ftl_cxt.clean_flag = 0;
 1681+ }
 1682+
 1683+ for (i = 0; i < count; )
 1684+ {
 1685+ uint32_t block = (sector + i) / ppb;
 1686+ uint32_t page = (sector + i) % ppb;
 1687+
 1688+ struct ftl_log_type* logentry = ftl_allocate_log_entry(block);
 1689+ if (logentry == (struct ftl_log_type*)0) return 1;
 1690+ if (page == 0 && count - i >= ppb)
 1691+ {
 1692+ uint32_t vblock = (*logentry).scatteredvblock;
 1693+ (*logentry).scatteredvblock = 0xFFFF;
 1694+ if ((*logentry).pagesused != 0)
 1695+ {
 1696+ ftl_release_pool_block(vblock);
 1697+ vblock = ftl_allocate_pool_block();
 1698+ if (vblock == 0xFFFFFFFF) return 1;
 1699+ }
 1700+ ftl_cxt.nextblockusn++;
 1701+ for (j = 0; j < ppb; j++)
 1702+ {
 1703+ memset(&ftl_sparebuffer, 0xFF, 0x40);
 1704+ ftl_sparebuffer.user.lpn = sector + i + j;
 1705+ ftl_sparebuffer.user.usn = ftl_cxt.nextblockusn;
 1706+ ftl_sparebuffer.user.type = 0x40;
 1707+ if (j == ppb - 1) ftl_sparebuffer.user.type = 0x41;
 1708+ while (ftl_vfl_write(vblock * ppb + j,
 1709+ &((uint8_t*)buffer)[(i + j) << 11],
 1710+ &ftl_sparebuffer) != 0);
 1711+ }
 1712+ ftl_release_pool_block(ftl_map[block]);
 1713+ ftl_map[block] = vblock;
 1714+ i += ppb;
 1715+ }
 1716+ else
 1717+ {
 1718+ if ((*logentry).pagesused == ppb)
 1719+ {
 1720+ ftl_remove_scattered_block(logentry);
 1721+ logentry = ftl_allocate_log_entry(block);
 1722+ if (logentry == (struct ftl_log_type*)0) return 1;
 1723+ }
 1724+ memset(&ftl_sparebuffer, 0xFF, 0x40);
 1725+ ftl_sparebuffer.user.lpn = sector + i;
 1726+ ftl_sparebuffer.user.usn = ++ftl_cxt.nextblockusn;
 1727+ ftl_sparebuffer.user.type = 0x40;
 1728+ uint32_t abspage = (*logentry).scatteredvblock * ppb
 1729+ + (*logentry).pagesused++;
 1730+ if (ftl_vfl_write(abspage, &((uint8_t*)buffer)[i << 11],
 1731+ &ftl_sparebuffer) == 0)
 1732+ {
 1733+ if ((*logentry).pageoffsets[page] == 0xFFFF)
 1734+ (*logentry).pagescurrent++;
 1735+ (*logentry).pageoffsets[page] = (*logentry).pagesused - 1;
 1736+ ftl_check_still_sequential(logentry, page);
 1737+ i++;
 1738+ }
 1739+ }
 1740+ }
 1741+ if (ftl_cxt.swapcounter >= 300)
 1742+ {
 1743+ ftl_cxt.swapcounter -= 20;
 1744+ for (i = 0; i < 4; i++) if (ftl_swap_blocks() == 0) break;
 1745+ }
 1746+ if (ftl_cxt.erasedirty == 1)
 1747+ {
 1748+ ftl_cxt.erasedirty = 0;
 1749+ for (i = 0; i < 8; i++)
 1750+ if (ftl_erasectr_dirt[i] >= 100)
 1751+ {
 1752+ ftl_next_ctrl_pool_page();
 1753+ ftl_save_erasectr_page(i);
 1754+ }
 1755+ }
 1756+ return 0;
 1757+}
 1758+#endif
 1759+
 1760+
 1761+#ifndef FTL_READONLY
 1762+// Exposed function: Performes a sync / unmount, i.e. commits all scattered page blocks,
 1763+// distributes wear, and commits the FTL context.
 1764+uint32_t storage_sync()
 1765+{
 1766+ uint32_t i;
 1767+ uint32_t rc = 0;
 1768+ uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
 1769+ if (ftl_cxt.clean_flag == 1) return 0;
 1770+
 1771+ if (ftl_cxt.swapcounter >= 20)
 1772+ for (i = 0; i < 4; i++)
 1773+ if (ftl_swap_blocks() == 0)
 1774+ {
 1775+ ftl_cxt.swapcounter -= 20;
 1776+ break;
 1777+ }
 1778+ for (i = 0; i < 0x11; i++)
 1779+ {
 1780+ if (ftl_log[i].scatteredvblock == 0xFFFF) continue;
 1781+ ftl_cxt.nextblockusn++;
 1782+ if (ftl_log[i].issequential == 1)
 1783+ rc |= ftl_commit_sequential(&ftl_log[i]);
 1784+ else rc |= ftl_commit_scattered(&ftl_log[i]);
 1785+ }
 1786+ if (rc == 0)
 1787+ for (i = 0; i < 5; i++)
 1788+ if (ftl_commit_cxt() == 0) return 0;
 1789+ else ftl_cxt.ftlctrlpage |= ppb - 1;
 1790+ return 1;
 1791+}
 1792+#endif
 1793+
 1794+
 1795+uint32_t storage_get_sector_count()
 1796+{
 1797+ return (*ftl_nand_type).pagesperblock * ftl_banks * (*ftl_nand_type).userblocks;
 1798+}
 1799+
 1800+
 1801+/* Initializes and mounts the FTL.
 1802+ As long as nothing was written, you won't need to unmount it.
 1803+ Before shutting down after writing something, call storage_sync(),
 1804+ which will just do nothing if everything was already clean. */
 1805+uint32_t storage_init(void)
 1806+{
 1807+ uint32_t i;
 1808+ uint32_t result = 0;
 1809+ uint32_t foundsignature, founddevinfo, blockwiped, repaired, skip;
 1810+
 1811+ if (ftl_initialized) return 0;
 1812+
 1813+ if (nand_init() != 0) return 1;
 1814+ ftl_banks = 0;
 1815+ for (i = 0; i < 4; i++)
 1816+ if (nand_get_device_type(i) != 0) ftl_banks = i + 1;
 1817+ ftl_nand_type = nand_get_device_type(0);
 1818+ foundsignature = 0;
 1819+ blockwiped = 1;
 1820+ for (i = 0; i < (*ftl_nand_type).pagesperblock; i++)
 1821+ {
 1822+ result = nand_read_page(0, i, ftl_buffer, (uint32_t*)0, 1, 1);
 1823+ if ((result & 0x11F) == 0)
 1824+ {
 1825+ blockwiped = 0;
 1826+ if (((uint32_t*)ftl_buffer)[0] != 0x41303034) continue;
 1827+ foundsignature = 1;
 1828+ break;
 1829+ }
 1830+ else if ((result & 2) != 2) blockwiped = 0;
 1831+ }
 1832+ founddevinfo = ftl_has_devinfo();
 1833+
 1834+ repaired = 0;
 1835+ skip = 0;
 1836+
 1837+ if (founddevinfo == 0) return 1;
 1838+
 1839+ if (foundsignature != 0 && (result & 0x11F) != 0) return 1;
 1840+
 1841+ if (ftl_vfl_open() == 0)
 1842+ if (ftl_open() == 0)
 1843+ {
 1844+ ftl_initialized = 1;
 1845+ return 0;
 1846+ }
 1847+
 1848+ return 1;
 1849+}
Index: embios/branches/4g_compat/target/ipodnano2g/lcd.h
@@ -0,0 +1,43 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __LCD_H__
 26+#define __LCD_H__
 27+
 28+
 29+#include "global.h"
 30+
 31+
 32+#define LCD_WIDTH 176
 33+#define LCD_HEIGHT 132
 34+#define LCD_FORMAT rgb565
 35+#define LCD_BYTESPERPIXEL 2
 36+#define LCD_FRAMEBUFSIZE (LCD_WIDTH * LCD_HEIGHT * LCD_BYTESPERPIXEL)
 37+
 38+
 39+void displaylcd(unsigned int startx, unsigned int endx,
 40+ unsigned int starty, unsigned int endy, void* data, int color);
 41+void displaylcd_sync();
 42+
 43+
 44+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/aes.c
@@ -0,0 +1,91 @@
 2+//
 3+//
 4+// Copyright 2009 TheSeven
 5+//
 6+//
 7+// This file is part of the Linux4Nano toolkit.
 8+//
 9+// TheSeven's iBugger is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// TheSeven's iBugger is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include <toolkit.h>
 26+#include <aes.h>
 27+
 28+
 29+void aes_encrypt(uint32_t keytype, void* data, uint32_t size)
 30+{
 31+ uint32_t ptr, i;
 32+ uint32_t go = 1;
 33+ PWRCONEXT &= ~0x400;
 34+ AESTYPE = keytype;
 35+ AESUNKREG0 = 1;
 36+ AESUNKREG0 = 0;
 37+ AESCONTROL = 1;
 38+ AESKEYLEN = 9;
 39+ AESOUTSIZE = size;
 40+ AESAUXSIZE = 0x10;
 41+ AESINSIZE = 0x10;
 42+ AESSIZE3 = 0x10;
 43+ for (ptr = 0; ptr < (size >> 2); ptr += 4)
 44+ {
 45+ AESOUTADDR = (uint32_t)data + (ptr << 2);
 46+ AESINADDR = (uint32_t)data + (ptr << 2);
 47+ AESAUXADDR = (uint32_t)data + (ptr << 2);
 48+ if (ptr != 0)
 49+ for (i = 0; i < 4; i++)
 50+ ((uint32_t*)data)[ptr + i] ^= ((uint32_t*)data)[ptr + i - 4];
 51+ clean_dcache();
 52+ AESSTATUS = 6;
 53+ AESGO = go;
 54+ go = 3;
 55+ while ((AESSTATUS & 6) == 0);
 56+ invalidate_dcache();
 57+ }
 58+ AESCONTROL = 0;
 59+ PWRCONEXT |= 0x400;
 60+}
 61+
 62+void aes_decrypt(uint32_t keytype, void* data, uint32_t size)
 63+{
 64+ uint32_t ptr, i;
 65+ uint32_t go = 1;
 66+ PWRCONEXT &= ~0x400;
 67+ AESTYPE = keytype;
 68+ AESUNKREG0 = 1;
 69+ AESUNKREG0 = 0;
 70+ AESCONTROL = 1;
 71+ AESKEYLEN = 8;
 72+ AESOUTSIZE = size;
 73+ AESAUXSIZE = 0x10;
 74+ AESINSIZE = 0x10;
 75+ AESSIZE3 = 0x10;
 76+ for (ptr = (size >> 2) - 4; ; ptr -= 4)
 77+ {
 78+ AESOUTADDR = (uint32_t)data + (ptr << 2);
 79+ AESINADDR = (uint32_t)data + (ptr << 2);
 80+ AESAUXADDR = (uint32_t)data + (ptr << 2);
 81+ clean_dcache();
 82+ AESSTATUS = 6;
 83+ AESGO = go;
 84+ go = 3;
 85+ while ((AESSTATUS & 6) == 0);
 86+ invalidate_dcache();
 87+ if (!ptr) break;
 88+ for (i = 0; i < 4; i++) ((uint32_t*)data)[ptr + i] ^= ((uint32_t*)data)[ptr + i - 4];
 89+ }
 90+ AESCONTROL = 0;
 91+ PWRCONEXT |= 0x400;
 92+}
Index: embios/branches/4g_compat/target/ipodnano2g/storage.h
@@ -0,0 +1,36 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __FTL_H__
 26+#define __FTL_H__
 27+
 28+#include "global.h"
 29+
 30+uint32_t storage_init();
 31+uint32_t storage_read(uint32_t sector, uint32_t count, void* buffer);
 32+uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer);
 33+uint32_t storage_sync();
 34+uint32_t storage_get_sector_count();
 35+
 36+
 37+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/config.h
@@ -0,0 +1,28 @@
 2+//
 3+//
 4+// Copyright 2009 TheSeven
 5+//
 6+//
 7+// This file is part of the Linux4Nano toolkit.
 8+//
 9+// TheSeven's iBugger is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// TheSeven's iBugger is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+//#define NAND_DEBUG
 26+//#define NAND_TRACE
 27+//#define VFL_TRACE
 28+//#define FTL_TRACE
 29+
Index: embios/branches/4g_compat/target/ipodnano2g/aes.h
@@ -0,0 +1,34 @@
 2+//
 3+//
 4+// Copyright 2009 TheSeven
 5+//
 6+//
 7+// This file is part of the Linux4Nano toolkit.
 8+//
 9+// TheSeven's iBugger is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// TheSeven's iBugger is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __AES_H__
 26+#define __AES_H__
 27+
 28+#include <toolkit.h>
 29+
 30+
 31+void aes_encrypt(uint32_t keytype, void* data, uint32_t size);
 32+void aes_decrypt(uint32_t keytype, void* data, uint32_t size);
 33+
 34+
 35+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/nand.c
@@ -0,0 +1,419 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+#include "util.h"
 27+#include "timer.h"
 28+#include "nand.h"
 29+#include "i2c.h"
 30+
 31+#define NAND_CMD_READ 0x00
 32+#define NAND_CMD_PROGCNFRM 0x10
 33+#define NAND_CMD_READ2 0x30
 34+#define NAND_CMD_BLOCKERASE 0x60
 35+#define NAND_CMD_GET_STATUS 0x70
 36+#define NAND_CMD_PROGRAM 0x80
 37+#define NAND_CMD_ERASECNFRM 0xD0
 38+#define NAND_CMD_RESET 0xFF
 39+
 40+#define NAND_STATUS_READY 0x40
 41+
 42+#define NAND_DEVICEINFOTABLE_ENTRIES 33
 43+
 44+static const struct nand_device_info_type nand_deviceinfotable[] =
 45+{
 46+ {0x1580F1EC, 1024, 968, 0x40, 6, 2, 1, 2, 1},
 47+ {0x1580DAEC, 2048, 1936, 0x40, 6, 2, 1, 2, 1},
 48+ {0x15C1DAEC, 2048, 1936, 0x40, 6, 2, 1, 2, 1},
 49+ {0x1510DCEC, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
 50+ {0x95C1DCEC, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
 51+ {0x2514DCEC, 2048, 1936, 0x80, 7, 2, 1, 2, 1},
 52+ {0x2514D3EC, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
 53+ {0x2555D3EC, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
 54+ {0x2555D5EC, 8192, 7744, 0x80, 7, 2, 1, 2, 1},
 55+ {0x2585D3AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
 56+ {0x9580DCAD, 4096, 3872, 0x40, 6, 3, 2, 3, 2},
 57+ {0xA514D3AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
 58+ {0xA550D3AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
 59+ {0xA560D5AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
 60+ {0xA555D5AD, 8192, 7744, 0x80, 7, 3, 2, 3, 2},
 61+ {0xA585D598, 8320, 7744, 0x80, 7, 3, 1, 2, 1},
 62+ {0xA584D398, 4160, 3872, 0x80, 7, 3, 1, 2, 1},
 63+ {0x95D1D32C, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
 64+ {0x1580DC2C, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
 65+ {0x15C1D32C, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
 66+ {0x9590DC2C, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
 67+ {0xA594D32C, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
 68+ {0x2584DC2C, 2048, 1936, 0x80, 7, 2, 1, 2, 1},
 69+ {0xA5D5D52C, 8192, 7744, 0x80, 7, 3, 2, 2, 1},
 70+ {0x95D1D389, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
 71+ {0x1580DC89, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
 72+ {0x15C1D389, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
 73+ {0x9590DC89, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
 74+ {0xA594D389, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
 75+ {0x2584DC89, 2048, 1936, 0x80, 7, 2, 1, 2, 1},
 76+ {0xA5D5D589, 8192, 7744, 0x80, 7, 2, 1, 2, 1},
 77+ {0xA514D320, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
 78+ {0xA555D520, 8192, 3872, 0x80, 7, 2, 1, 2, 1}
 79+};
 80+
 81+uint8_t nand_tunk1[4];
 82+uint8_t nand_twp[4];
 83+uint8_t nand_tunk2[4];
 84+uint8_t nand_tunk3[4];
 85+uint32_t nand_type[4];
 86+
 87+static uint8_t nand_ctrl[0x200] __attribute__((aligned(16)));
 88+static uint8_t nand_spare[0x40] __attribute__((aligned(16)));
 89+static uint8_t nand_ecc[0x30] __attribute__((aligned(16)));
 90+
 91+
 92+uint32_t nand_wait_rbbdone(void)
 93+{
 94+ uint32_t timeout = USEC_TIMER;
 95+ while ((FMCSTAT & FMCSTAT_RBBDONE) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
 96+ FMCSTAT = FMCSTAT_RBBDONE;
 97+ return 0;
 98+}
 99+
 100+uint32_t nand_wait_cmddone(void)
 101+{
 102+ uint32_t timeout = USEC_TIMER;
 103+ while ((FMCSTAT & FMCSTAT_CMDDONE) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
 104+ FMCSTAT = FMCSTAT_CMDDONE;
 105+ return 0;
 106+}
 107+
 108+uint32_t nand_wait_addrdone(void)
 109+{
 110+ uint32_t timeout = USEC_TIMER;
 111+ while ((FMCSTAT & FMCSTAT_ADDRDONE) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
 112+ FMCSTAT = FMCSTAT_ADDRDONE;
 113+ return 0;
 114+}
 115+
 116+uint32_t nand_wait_chip_ready(uint32_t bank)
 117+{
 118+ uint32_t timeout = USEC_TIMER;
 119+ while ((FMCSTAT & (FMCSTAT_BANK0READY << bank)) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
 120+ FMCSTAT = (FMCSTAT_BANK0READY << bank);
 121+ return 0;
 122+}
 123+
 124+void nand_set_fmctrl0(uint32_t bank, uint32_t flags)
 125+{
 126+ FMCTRL0 = (nand_tunk1[bank] << 16) | (nand_twp[bank] << 12)
 127+ | (1 << 11) | 1 | (1 << (bank + 1)) | flags;
 128+}
 129+
 130+uint32_t nand_send_cmd(uint32_t cmd)
 131+{
 132+ FMCMD = cmd;
 133+ return nand_wait_rbbdone();
 134+}
 135+
 136+uint32_t nand_send_address(uint32_t page, uint32_t offset)
 137+{
 138+ FMANUM = 4;
 139+ FMADDR0 = (page << 16) | offset;
 140+ FMADDR1 = (page >> 16) & 0xFF;
 141+ FMCTRL1 = FMCTRL1_DOTRANSADDR;
 142+ return nand_wait_cmddone();
 143+}
 144+
 145+uint32_t nand_reset(uint32_t bank)
 146+{
 147+ nand_set_fmctrl0(bank, 0);
 148+ if (nand_send_cmd(NAND_CMD_RESET)) return 1;
 149+ if (nand_wait_chip_ready(bank)) return 1;
 150+ FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
 151+ sleep(1000);
 152+ return 0;
 153+}
 154+
 155+uint32_t nand_wait_status_ready(uint32_t bank)
 156+{
 157+ uint32_t timeout = USEC_TIMER;
 158+ nand_set_fmctrl0(bank, 0);
 159+ if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)))
 160+ FMCSTAT = (FMCSTAT_BANK0READY << bank);
 161+ FMCTRL1 = FMCTRL1_CLEARRFIFO;
 162+ if (nand_send_cmd(NAND_CMD_GET_STATUS)) return 1;
 163+ while (1)
 164+ {
 165+ if (TIMEOUT_EXPIRED(timeout, 200)) return 1;
 166+ FMDNUM = 0;
 167+ FMCTRL1 = FMCTRL1_DOREADDATA;
 168+ if (nand_wait_addrdone()) return 1;
 169+ if ((FMFIFO & NAND_STATUS_READY)) break;
 170+ FMCTRL1 = FMCTRL1_CLEARRFIFO;
 171+ }
 172+ FMCTRL1 = FMCTRL1_CLEARRFIFO;
 173+ return nand_send_cmd(NAND_CMD_READ);
 174+}
 175+
 176+uint32_t nand_transfer_data(uint32_t bank, uint32_t direction, void* buffer, uint32_t size)
 177+{
 178+ uint32_t timeout = USEC_TIMER;
 179+ nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
 180+ FMDNUM = size - 1;
 181+ FMCTRL1 = FMCTRL1_DOREADDATA << direction;
 182+ DMACON3 = (2 << DMACON_DEVICE_SHIFT)
 183+ | (direction << DMACON_DIRECTION_SHIFT)
 184+ | (2 << DMACON_DATA_SIZE_SHIFT)
 185+ | (3 << DMACON_BURST_LEN_SHIFT);
 186+ while ((DMAALLST & DMAALLST_CHAN3_MASK))
 187+ DMACOM3 = DMACOM_CLEARBOTHDONE;
 188+ DMABASE3 = (uint32_t)buffer;
 189+ DMATCNT3 = (size >> 4) - 1;
 190+ clean_dcache();
 191+ DMACOM3 = 4;
 192+ while ((DMAALLST & DMAALLST_DMABUSY3)) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
 193+ if (!direction) invalidate_dcache();
 194+ if (nand_wait_addrdone()) return 1;
 195+ if (!direction) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
 196+ else FMCTRL1 = FMCTRL1_CLEARRFIFO;
 197+ return 0;
 198+}
 199+
 200+uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer)
 201+{
 202+ uint32_t timeout = USEC_TIMER;
 203+ ECC_INT_CLR = 1;
 204+ SRCPND = INTMSK_ECC;
 205+ ECC_UNK1 = size;
 206+ ECC_DATA_PTR = (uint32_t)databuffer;
 207+ ECC_SPARE_PTR = (uint32_t)sparebuffer;
 208+ clean_dcache();
 209+ ECC_CTRL = ECCCTRL_STARTDECODING;
 210+ while (!(SRCPND & INTMSK_ECC)) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
 211+ invalidate_dcache();
 212+ ECC_INT_CLR = 1;
 213+ SRCPND = INTMSK_ECC;
 214+ return ECC_RESULT;
 215+}
 216+
 217+uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer)
 218+{
 219+ uint32_t timeout = USEC_TIMER;
 220+ ECC_INT_CLR = 1;
 221+ SRCPND = INTMSK_ECC;
 222+ ECC_UNK1 = size;
 223+ ECC_DATA_PTR = (uint32_t)databuffer;
 224+ ECC_SPARE_PTR = (uint32_t)sparebuffer;
 225+ clean_dcache();
 226+ ECC_CTRL = ECCCTRL_STARTENCODING;
 227+ while (!(SRCPND & INTMSK_ECC)) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
 228+ invalidate_dcache();
 229+ ECC_INT_CLR = 1;
 230+ SRCPND = INTMSK_ECC;
 231+ return 0;
 232+}
 233+
 234+uint32_t nand_check_empty(uint8_t* buffer)
 235+{
 236+ uint32_t i, count;
 237+ count = 0;
 238+ for (i = 0; i < 0x40; i++) if (buffer[i] != 0xFF) count++;
 239+ if (count < 2) return 1;
 240+ return 0;
 241+}
 242+
 243+uint32_t nand_get_chip_type(uint32_t bank)
 244+{
 245+ uint32_t result;
 246+ if (nand_reset(bank)) return 0xFFFFFFFF;
 247+ if (nand_send_cmd(0x90)) return 0xFFFFFFFF;
 248+ FMANUM = 0;
 249+ FMADDR0 = 0;
 250+ FMCTRL1 = FMCTRL1_DOTRANSADDR;
 251+ if (nand_wait_cmddone()) return 0xFFFFFFFF;
 252+ FMDNUM = 4;
 253+ FMCTRL1 = FMCTRL1_DOREADDATA;
 254+ if (nand_wait_addrdone()) return 0xFFFFFFFF;
 255+ result = FMFIFO;
 256+ FMCTRL1 = FMCTRL1_CLEARRFIFO;
 257+ return result;
 258+}
 259+
 260+uint32_t nand_read_page(uint32_t bank, uint32_t page, void* data,
 261+ void* sparebuffer, uint32_t doecc, uint32_t checkempty)
 262+{
 263+ uint32_t rc, eccresult;
 264+ uint8_t* spare = nand_spare;
 265+ if (sparebuffer) spare = sparebuffer;
 266+ nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
 267+ if (nand_send_cmd(NAND_CMD_READ)) return 1;
 268+ if (nand_send_address(page, data ? 0 : 0x800)) return 1;
 269+ if (nand_send_cmd(NAND_CMD_READ2)) return 1;
 270+ if (nand_wait_status_ready(bank)) return 1;
 271+ if (data) if (nand_transfer_data(bank, 0, data, 0x800)) return 1;
 272+ rc = 0;
 273+ if (!doecc)
 274+ {
 275+ if (sparebuffer)
 276+ {
 277+ if (nand_transfer_data(bank, 0, spare, 0x40)) return 1;
 278+ if (checkempty)
 279+ rc = nand_check_empty((uint8_t*)spare) << 1;
 280+ }
 281+ return rc;
 282+ }
 283+ if (nand_transfer_data(bank, 0, spare, 0x40)) return 1;
 284+ if (data)
 285+ {
 286+ memcpy(nand_ecc, &((uint8_t*)spare)[0xC], 0x28);
 287+ rc |= (ecc_decode(3, data, nand_ecc) & 0xF) << 4;
 288+ }
 289+ memset(nand_ctrl, 0xFF, 0x200);
 290+ memcpy(nand_ctrl, spare, 0xC);
 291+ memcpy(nand_ecc, &((uint8_t*)spare)[0x34], 0xC);
 292+ eccresult = ecc_decode(0, nand_ctrl, nand_ecc);
 293+ rc |= (eccresult & 0xF) << 8;
 294+ if (spare)
 295+ {
 296+ if (eccresult & 1) memset(spare, 0xFF, 0xC);
 297+ else memcpy(spare, nand_ctrl, 0xC);
 298+ }
 299+ if (checkempty) rc |= nand_check_empty(spare) << 1;
 300+ return rc;
 301+}
 302+
 303+uint32_t nand_write_page(uint32_t bank, uint32_t page, void* data,
 304+ void* sparebuffer, uint32_t doecc)
 305+{
 306+ uint8_t* spare = nand_spare;
 307+ if (sparebuffer) spare = sparebuffer;
 308+ else memset(spare, 0xFF, 0x40);
 309+ if (doecc)
 310+ {
 311+ if (ecc_encode(3, data, nand_ecc)) return 1;
 312+ memcpy(&spare[0xC], nand_ecc, 0x28);
 313+ memset(nand_ctrl, 0xFF, 0x200);
 314+ memcpy(nand_ctrl, spare, 0xC);
 315+ if (ecc_encode(0, nand_ctrl, nand_ecc)) return 1;
 316+ memcpy(&spare[0x34], nand_ecc, 0xC);
 317+ }
 318+ nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
 319+ if (nand_send_cmd(NAND_CMD_PROGRAM)) return 1;
 320+ if (nand_send_address(page, data ? 0 : 0x800)) return 1;
 321+ if (data) if (nand_transfer_data(bank, 1, data, 0x800)) return 1;
 322+ if (sparebuffer || doecc)
 323+ if (nand_transfer_data(bank, 1, spare, 0x40)) return 1;
 324+ if (nand_send_cmd(NAND_CMD_PROGCNFRM)) return 1;
 325+ return nand_wait_status_ready(bank);
 326+}
 327+
 328+uint32_t nand_block_erase(uint32_t bank, uint32_t page)
 329+{
 330+ nand_set_fmctrl0(bank, 0);
 331+ if (nand_send_cmd(NAND_CMD_BLOCKERASE)) return 1;
 332+ FMANUM = 2;
 333+ FMADDR0 = page;
 334+ FMCTRL1 = FMCTRL1_DOTRANSADDR;
 335+ if (nand_wait_cmddone()) return 1;
 336+ if (nand_send_cmd(NAND_CMD_ERASECNFRM)) return 1;
 337+ return nand_wait_status_ready(bank);
 338+}
 339+
 340+uint32_t nand_block_erase_fast(uint32_t page)
 341+{
 342+ uint32_t i, rc = 0;
 343+ for (i = 0; i < 4; i++)
 344+ {
 345+ if (nand_type[i] == 0xFFFFFFFF) continue;
 346+ nand_set_fmctrl0(i, 0);
 347+ if (nand_send_cmd(NAND_CMD_BLOCKERASE))
 348+ {
 349+ rc |= 1 << i;
 350+ continue;
 351+ }
 352+ FMANUM = 2;
 353+ FMADDR0 = page;
 354+ FMCTRL1 = FMCTRL1_DOTRANSADDR;
 355+ if (nand_wait_cmddone())
 356+ {
 357+ rc |= 1 << i;
 358+ continue;
 359+ }
 360+ if (nand_send_cmd(NAND_CMD_ERASECNFRM)) rc |= 1 << i;
 361+ }
 362+ for (i = 0; i < 4; i++)
 363+ {
 364+ if (nand_type[i] == 0xFFFFFFFF) continue;
 365+ if (rc & (1 << i)) continue;
 366+ if (nand_wait_status_ready(i)) rc |= 1 << i;
 367+ }
 368+ return rc;
 369+}
 370+
 371+const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
 372+{
 373+ if (nand_type[bank] == 0xFFFFFFFF)
 374+ return (struct nand_device_info_type*)0;
 375+ return &nand_deviceinfotable[nand_type[bank]];
 376+}
 377+
 378+uint32_t nand_init()
 379+{
 380+ uint32_t type;
 381+ uint32_t i, j;
 382+ PWRCONEXT &= ~0x40;
 383+ PWRCON &= ~0x100010;
 384+ i2csendbyte(0xE6, 0x35, 0x15);
 385+ i2csendbyte(0xE6, 0x36, 0x01);
 386+ PCON2 = 0x33333333;
 387+ PDAT2 = 0;
 388+ PCON3 = 0x11113333;
 389+ PDAT3 = 0;
 390+ PCON4 = 0x33333333;
 391+ PDAT4 = 0;
 392+ PCON5 = (PCON5 & ~0xF) | 3;
 393+ PUNK5 = 1;
 394+ sleep(10000);
 395+ for (i = 0; i < 4; i++)
 396+ {
 397+ nand_tunk1[i] = 7;
 398+ nand_twp[i] = 7;
 399+ nand_tunk2[i] = 7;
 400+ nand_tunk3[i] = 7;
 401+ type = nand_get_chip_type(i);
 402+ nand_type[i] = 0xFFFFFFFF;
 403+ if (type == 0xFFFFFFFF) continue;
 404+ for (j = 0; ; j++)
 405+ {
 406+ if (j == NAND_DEVICEINFOTABLE_ENTRIES) break;
 407+ else if (nand_deviceinfotable[j].id == type)
 408+ {
 409+ nand_type[i] = j;
 410+ break;
 411+ }
 412+ }
 413+ nand_tunk1[i] = nand_deviceinfotable[nand_type[i]].tunk1;
 414+ nand_twp[i] = nand_deviceinfotable[nand_type[i]].twp;
 415+ nand_tunk2[i] = nand_deviceinfotable[nand_type[i]].tunk2;
 416+ nand_tunk3[i] = nand_deviceinfotable[nand_type[i]].tunk3;
 417+ }
 418+ if (nand_type[0] == 0xFFFFFFFF) return 1;
 419+ return 0;
 420+}
Index: embios/branches/4g_compat/target/ipodnano2g/i2c.h
@@ -0,0 +1,37 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __I2C_H__
 26+#define __I2C_H__
 27+
 28+
 29+#include "global.h"
 30+
 31+
 32+extern void i2csend(uint32_t device, uint32_t address, void* data, uint32_t length);
 33+extern void i2crecv(uint32_t device, uint32_t address, void* data, uint32_t length);
 34+extern void i2csendbyte(uint32_t device, uint32_t address, uint32_t data);
 35+extern uint32_t i2crecvbyte(uint32_t device, uint32_t address);
 36+
 37+
 38+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/hash.c
@@ -0,0 +1,42 @@
 2+//
 3+//
 4+// Copyright 2009 TheSeven
 5+//
 6+//
 7+// This file is part of the Linux4Nano toolkit.
 8+//
 9+// TheSeven's iBugger is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// TheSeven's iBugger is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include <toolkit.h>
 26+#include <hash.h>
 27+
 28+
 29+void hash(void* data, uint32_t size, void* result)
 30+{
 31+ uint32_t ptr, i;
 32+ uint32_t ctrl = 2;
 33+ PWRCONEXT &= ~4;
 34+ for (ptr = 0; ptr < size; ptr += 0x10)
 35+ {
 36+ for (i = 0; i < 0x10; i++) HASHDATAIN[i] = ((uint32_t*)data)[ptr + i];
 37+ HASHCTRL = ctrl;
 38+ ctrl = 0xA;
 39+ while (HASHCTRL & 1);
 40+ }
 41+ for (i = 0; i < 5; i ++) ((uint32_t*)result)[i] = HASHRESULT[i];
 42+ PWRCONEXT |= 4;
 43+}
Index: embios/branches/4g_compat/target/ipodnano2g/timer.h
@@ -0,0 +1,42 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __TIMER_H__
 26+#define __TIMER_H__
 27+
 28+#include "global.h"
 29+
 30+
 31+#define TIME_AFTER(a,b) ((long)(b) - (long)(a) < 0)
 32+#define TIME_BEFORE(a,b) TIME_AFTER(b,a)
 33+#define TIMEOUT_EXPIRED(a,b) TIME_AFTER(USEC_TIMER,a + b)
 34+
 35+
 36+static inline void sleep(long duration) /* in usec steps */
 37+{
 38+ long timestamp = USEC_TIMER;
 39+ while (!TIMEOUT_EXPIRED(timestamp, duration));
 40+}
 41+
 42+
 43+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/nand.h
@@ -0,0 +1,62 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __NAND_H__
 26+#define __NAND_H__
 27+
 28+#include "global.h"
 29+
 30+
 31+struct nand_device_info_type
 32+{
 33+ uint32_t id;
 34+ uint16_t blocks;
 35+ uint16_t userblocks;
 36+ uint16_t pagesperblock;
 37+ uint8_t blocksizeexponent;
 38+ uint8_t tunk1;
 39+ uint8_t twp;
 40+ uint8_t tunk2;
 41+ uint8_t tunk3;
 42+} __attribute__((packed));
 43+
 44+uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
 45+ void* sparebuffer, uint32_t doecc,
 46+ uint32_t checkempty);
 47+uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
 48+ void* sparebuffer, uint32_t doecc);
 49+uint32_t nand_block_erase(uint32_t bank, uint32_t page);
 50+
 51+uint32_t nand_read_page_fast(uint32_t page, void* databuffer,
 52+ void* sparebuffer, uint32_t doecc,
 53+ uint32_t checkempty);
 54+uint32_t nand_write_page_fast(uint32_t page, void* databuffer,
 55+ void* sparebuffer, uint32_t doecc);
 56+uint32_t nand_block_erase_fast(uint32_t page);
 57+
 58+const struct nand_device_info_type* nand_get_device_type(uint32_t bank);
 59+uint32_t nand_reset(uint32_t bank);
 60+uint32_t nand_init();
 61+
 62+
 63+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/s5l8701.h
@@ -0,0 +1,245 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __S5L8701_H__
 26+#define __S5L8701_H__
 27+
 28+#include "global.h"
 29+
 30+
 31+/////CLKCON/////
 32+#define CLKCON (*((volatile uint32_t*)(0x3C500000)))
 33+#define PLL0PMS (*((volatile uint32_t*)(0x3C500004)))
 34+#define PLL1PMS (*((volatile uint32_t*)(0x3C500008)))
 35+#define PLL2PMS (*((volatile uint32_t*)(0x3C50000C)))
 36+#define PLL0LCNT (*((volatile uint32_t*)(0x3C500014)))
 37+#define PLL1LCNT (*((volatile uint32_t*)(0x3C500018)))
 38+#define PLL2LCNT (*((volatile uint32_t*)(0x3C50001C)))
 39+#define PLLLOCK (*((volatile uint32_t*)(0x3C500020)))
 40+#define PLLCON (*((volatile uint32_t*)(0x3C500024)))
 41+#define PWRCON (*((volatile uint32_t*)(0x3C500028)))
 42+#define PWRMODE (*((volatile uint32_t*)(0x3C50002C)))
 43+#define SWRCON (*((volatile uint32_t*)(0x3C500030)))
 44+#define RSTSR (*((volatile uint32_t*)(0x3C500034)))
 45+#define DSPCLKMD (*((volatile uint32_t*)(0x3C500038)))
 46+#define CLKCON2 (*((volatile uint32_t*)(0x3C50003C)))
 47+#define PWRCONEXT (*((volatile uint32_t*)(0x3C500040)))
 48+
 49+
 50+/////ICU/////
 51+#define SRCPND (*((volatile uint32_t*)(0x39C00000)))
 52+#define INTMOD (*((volatile uint32_t*)(0x39C00004)))
 53+#define INTMSK (*((volatile uint32_t*)(0x39C00008)))
 54+#define INTPRIO (*((volatile uint32_t*)(0x39C0000C)))
 55+#define INTPND (*((volatile uint32_t*)(0x39C00010)))
 56+#define INTOFFSET (*((volatile uint32_t*)(0x39C00014)))
 57+#define EINTPOL (*((volatile uint32_t*)(0x39C00018)))
 58+#define EINTPEND (*((volatile uint32_t*)(0x39C0001C)))
 59+#define EINTMSK (*((volatile uint32_t*)(0x39C00020)))
 60+
 61+
 62+/////GPIO/////
 63+#define PCON0 (*((volatile uint32_t*)(0x3CF00000)))
 64+#define PDAT0 (*((volatile uint32_t*)(0x3CF00004)))
 65+#define PCON1 (*((volatile uint32_t*)(0x3CF00010)))
 66+#define PDAT1 (*((volatile uint32_t*)(0x3CF00014)))
 67+#define PCON2 (*((volatile uint32_t*)(0x3CF00020)))
 68+#define PDAT2 (*((volatile uint32_t*)(0x3CF00024)))
 69+#define PCON3 (*((volatile uint32_t*)(0x3CF00030)))
 70+#define PDAT3 (*((volatile uint32_t*)(0x3CF00034)))
 71+#define PCON4 (*((volatile uint32_t*)(0x3CF00040)))
 72+#define PDAT4 (*((volatile uint32_t*)(0x3CF00044)))
 73+#define PCON5 (*((volatile uint32_t*)(0x3CF00050)))
 74+#define PDAT5 (*((volatile uint32_t*)(0x3CF00054)))
 75+#define PUNK5 (*((volatile uint32_t*)(0x3CF0005C)))
 76+#define PCON6 (*((volatile uint32_t*)(0x3CF00060)))
 77+#define PDAT6 (*((volatile uint32_t*)(0x3CF00064)))
 78+#define PCON7 (*((volatile uint32_t*)(0x3CF00070)))
 79+#define PDAT7 (*((volatile uint32_t*)(0x3CF00074)))
 80+#define PCON10 (*((volatile uint32_t*)(0x3CF000A0)))
 81+#define PDAT10 (*((volatile uint32_t*)(0x3CF000A4)))
 82+#define PCON15 (*((volatile uint32_t*)(0x3CF000F0)))
 83+#define PUNK15 (*((volatile uint32_t*)(0x3CF000FC)))
 84+
 85+
 86+/////IODMA/////
 87+#define DMABASE0 (*((volatile uint32_t*)(0x38400000)))
 88+#define DMACON0 (*((volatile uint32_t*)(0x38400004)))
 89+#define DMATCNT0 (*((volatile uint32_t*)(0x38400008)))
 90+#define DMACADDR0 (*((volatile uint32_t*)(0x3840000C)))
 91+#define DMACTCNT0 (*((volatile uint32_t*)(0x38400010)))
 92+#define DMACOM0 (*((volatile uint32_t*)(0x38400014)))
 93+#define DMANOF0 (*((volatile uint32_t*)(0x38400018)))
 94+#define DMABASE1 (*((volatile uint32_t*)(0x38400020)))
 95+#define DMACON1 (*((volatile uint32_t*)(0x38400024)))
 96+#define DMATCNT1 (*((volatile uint32_t*)(0x38400028)))
 97+#define DMACADDR1 (*((volatile uint32_t*)(0x3840002C)))
 98+#define DMACTCNT1 (*((volatile uint32_t*)(0x38400030)))
 99+#define DMACOM1 (*((volatile uint32_t*)(0x38400034)))
 100+#define DMABASE2 (*((volatile uint32_t*)(0x38400040)))
 101+#define DMACON2 (*((volatile uint32_t*)(0x38400044)))
 102+#define DMATCNT2 (*((volatile uint32_t*)(0x38400048)))
 103+#define DMACADDR2 (*((volatile uint32_t*)(0x3840004C)))
 104+#define DMACTCNT2 (*((volatile uint32_t*)(0x38400050)))
 105+#define DMACOM2 (*((volatile uint32_t*)(0x38400054)))
 106+#define DMABASE3 (*((volatile uint32_t*)(0x38400060)))
 107+#define DMACON3 (*((volatile uint32_t*)(0x38400064)))
 108+#define DMATCNT3 (*((volatile uint32_t*)(0x38400068)))
 109+#define DMACADDR3 (*((volatile uint32_t*)(0x3840006C)))
 110+#define DMACTCNT3 (*((volatile uint32_t*)(0x38400070)))
 111+#define DMACOM3 (*((volatile uint32_t*)(0x38400074)))
 112+#define DMABASE4 (*((volatile uint32_t*)(0x38400080)))
 113+#define DMACON4 (*((volatile uint32_t*)(0x38400084)))
 114+#define DMATCNT4 (*((volatile uint32_t*)(0x38400088)))
 115+#define DMACADDR4 (*((volatile uint32_t*)(0x3840008C)))
 116+#define DMACTCNT4 (*((volatile uint32_t*)(0x38400090)))
 117+#define DMACOM4 (*((volatile uint32_t*)(0x38400094)))
 118+#define DMABASE5 (*((volatile uint32_t*)(0x384000A0)))
 119+#define DMACON5 (*((volatile uint32_t*)(0x384000A4)))
 120+#define DMATCNT5 (*((volatile uint32_t*)(0x384000A8)))
 121+#define DMACADDR5 (*((volatile uint32_t*)(0x384000AC)))
 122+#define DMACTCNT5 (*((volatile uint32_t*)(0x384000B0)))
 123+#define DMACOM5 (*((volatile uint32_t*)(0x384000B4)))
 124+#define DMABASE6 (*((volatile uint32_t*)(0x384000C0)))
 125+#define DMACON6 (*((volatile uint32_t*)(0x384000C4)))
 126+#define DMATCNT6 (*((volatile uint32_t*)(0x384000C8)))
 127+#define DMACADDR6 (*((volatile uint32_t*)(0x384000CC)))
 128+#define DMACTCNT6 (*((volatile uint32_t*)(0x384000D0)))
 129+#define DMACOM6 (*((volatile uint32_t*)(0x384000D4)))
 130+#define DMABASE7 (*((volatile uint32_t*)(0x384000E0)))
 131+#define DMACON7 (*((volatile uint32_t*)(0x384000E4)))
 132+#define DMATCNT7 (*((volatile uint32_t*)(0x384000E8)))
 133+#define DMACADDR7 (*((volatile uint32_t*)(0x384000EC)))
 134+#define DMACTCNT7 (*((volatile uint32_t*)(0x384000F0)))
 135+#define DMACOM7 (*((volatile uint32_t*)(0x384000F4)))
 136+#define DMAALLST (*((volatile uint32_t*)(0x38400180)))
 137+#define DMACON_DEVICE_SHIFT 30
 138+#define DMACON_DIRECTION_SHIFT 29
 139+#define DMACON_DATA_SIZE_SHIFT 22
 140+#define DMACON_BURST_LEN_SHIFT 19
 141+#define DMACOM_START 4
 142+#define DMACOM_CLEARBOTHDONE 7
 143+#define DMAALLST_WCOM0 (1 << 0)
 144+#define DMAALLST_HCOM0 (1 << 1)
 145+#define DMAALLST_DMABUSY0 (1 << 2)
 146+#define DMAALLST_HOLD_SKIP (1 << 3)
 147+#define DMAALLST_WCOM1 (1 << 4)
 148+#define DMAALLST_HCOM1 (1 << 5)
 149+#define DMAALLST_DMABUSY1 (1 << 6)
 150+#define DMAALLST_WCOM2 (1 << 8)
 151+#define DMAALLST_HCOM2 (1 << 9)
 152+#define DMAALLST_DMABUSY2 (1 << 10)
 153+#define DMAALLST_WCOM3 (1 << 12)
 154+#define DMAALLST_HCOM3 (1 << 13)
 155+#define DMAALLST_DMABUSY3 (1 << 14)
 156+#define DMAALLST_CHAN0_MASK (0xF << 0)
 157+#define DMAALLST_CHAN1_MASK (0xF << 4)
 158+#define DMAALLST_CHAN2_MASK (0xF << 8)
 159+#define DMAALLST_CHAN3_MASK (0xF << 12)
 160+
 161+
 162+/////FMC/////
 163+#define FMCTRL0 (*((volatile uint32_t*)(0x39400000)))
 164+#define FMCTRL1 (*((volatile uint32_t*)(0x39400004)))
 165+#define FMCMD (*((volatile uint32_t*)(0x39400008)))
 166+#define FMADDR0 (*((volatile uint32_t*)(0x3940000C)))
 167+#define FMADDR1 (*((volatile uint32_t*)(0x39400010)))
 168+#define FMANUM (*((volatile uint32_t*)(0x3940002C)))
 169+#define FMDNUM (*((volatile uint32_t*)(0x39400030)))
 170+#define FMCSTAT (*((volatile uint32_t*)(0x39400048)))
 171+#define FMFIFO (*((volatile uint32_t*)(0x39400080)))
 172+#define RS_ECC_CTRL (*((volatile uint32_t*)(0x39400100)))
 173+#define FMCTRL0_ENABLEDMA (1 << 10)
 174+#define FMCTRL0_UNK1 (1 << 11)
 175+#define FMCTRL1_DOTRANSADDR (1 << 0)
 176+#define FMCTRL1_DOREADDATA (1 << 1)
 177+#define FMCTRL1_DOWRITEDATA (1 << 2)
 178+#define FMCTRL1_CLEARWFIFO (1 << 6)
 179+#define FMCTRL1_CLEARRFIFO (1 << 7)
 180+#define FMCSTAT_RBB (1 << 0)
 181+#define FMCSTAT_RBBDONE (1 << 1)
 182+#define FMCSTAT_CMDDONE (1 << 2)
 183+#define FMCSTAT_ADDRDONE (1 << 3)
 184+#define FMCSTAT_BANK0READY (1 << 4)
 185+#define FMCSTAT_BANK1READY (1 << 5)
 186+#define FMCSTAT_BANK2READY (1 << 6)
 187+#define FMCSTAT_BANK3READY (1 << 7)
 188+
 189+
 190+/////ECC/////
 191+#define ECC_DATA_PTR (*((volatile uint32_t*)(0x39E00004)))
 192+#define ECC_SPARE_PTR (*((volatile uint32_t*)(0x39E00008)))
 193+#define ECC_CTRL (*((volatile uint32_t*)(0x39E0000C)))
 194+#define ECC_RESULT (*((volatile uint32_t*)(0x39E00010)))
 195+#define ECC_UNK1 (*((volatile uint32_t*)(0x39E00014)))
 196+#define ECC_INT_CLR (*((volatile uint32_t*)(0x39E00040)))
 197+#define INTMSK_ECC 0x80000
 198+#define ECCCTRL_STARTDECODING (1 << 0)
 199+#define ECCCTRL_STARTENCODING (1 << 1)
 200+#define ECCCTRL_STARTDECNOSYND (1 << 2)
 201+
 202+
 203+/////CLICKWHEEL/////
 204+#define WHEEL00 (*((volatile uint32_t*)(0x3C200000)))
 205+#define WHEEL04 (*((volatile uint32_t*)(0x3C200004)))
 206+#define WHEEL08 (*((volatile uint32_t*)(0x3C200008)))
 207+#define WHEEL0C (*((volatile uint32_t*)(0x3C20000C)))
 208+#define WHEEL10 (*((volatile uint32_t*)(0x3C200010)))
 209+#define WHEELINT (*((volatile uint32_t*)(0x3C200014)))
 210+#define WHEELRX (*((volatile uint32_t*)(0x3C200018)))
 211+#define WHEELTX (*((volatile uint32_t*)(0x3C20001C)))
 212+
 213+
 214+/////AES/////
 215+#define AESCONTROL (*((volatile uint32_t*)(0x39800000)))
 216+#define AESGO (*((volatile uint32_t*)(0x39800004)))
 217+#define AESUNKREG0 (*((volatile uint32_t*)(0x39800008)))
 218+#define AESSTATUS (*((volatile uint32_t*)(0x3980000C)))
 219+#define AESUNKREG1 (*((volatile uint32_t*)(0x39800010)))
 220+#define AESKEYLEN (*((volatile uint32_t*)(0x39800014)))
 221+#define AESOUTSIZE (*((volatile uint32_t*)(0x39800018)))
 222+#define AESOUTADDR (*((volatile uint32_t*)(0x39800020)))
 223+#define AESINSIZE (*((volatile uint32_t*)(0x39800024)))
 224+#define AESINADDR (*((volatile uint32_t*)(0x39800028)))
 225+#define AESAUXSIZE (*((volatile uint32_t*)(0x3980002C)))
 226+#define AESAUXADDR (*((volatile uint32_t*)(0x39800030)))
 227+#define AESSIZE3 (*((volatile uint32_t*)(0x39800034)))
 228+#define AESKEY ((volatile uint32_t*)(0x3980004C))
 229+#define AESTYPE (*((volatile uint32_t*)(0x3980006C)))
 230+#define AESIV ((volatile uint32_t*)(0x39800074))
 231+#define AESTYPE2 (*((volatile uint32_t*)(0x39800088)))
 232+#define AESUNKREG2 (*((volatile uint32_t*)(0x3980008C)))
 233+
 234+/////HASH/////
 235+#define HASHCTRL (*((volatile uint32_t*)(0x3C600000)))
 236+#define HASHRESULT ((volatile uint32_t*)(0x3C600020))
 237+#define HASHDATAIN ((volatile uint32_t*)(0x3C600040))
 238+
 239+
 240+/////TIMER/////
 241+#define FIVE_USEC_TIMER (((uint64_t)(*((volatile uint32_t*)(0x3C700080))) << 32) \
 242+ | (*((volatile uint32_t*)(0x3C700084)))) /* 64bit 5usec timer */
 243+#define USEC_TIMER ((long)(FIVE_USEC_TIMER * 5)) /* usecs */
 244+
 245+
 246+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/hash.h
@@ -0,0 +1,33 @@
 2+//
 3+//
 4+// Copyright 2009 TheSeven
 5+//
 6+//
 7+// This file is part of the Linux4Nano toolkit.
 8+//
 9+// TheSeven's iBugger is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// TheSeven's iBugger is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __HASH_H__
 26+#define __HASH_H__
 27+
 28+#include <toolkit.h>
 29+
 30+
 31+void hash(void* data, uint32_t size, void* result);
 32+
 33+
 34+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/crt0.S
@@ -0,0 +1,187 @@
 2+@
 3+@
 4+@ Copyright 2010 TheSeven
 5+@
 6+@
 7+@ This file is part of emBIOS.
 8+@
 9+@ emBIOS is free software: you can redistribute it and/or
 10+@ modify it under the terms of the GNU General Public License as
 11+@ published by the Free Software Foundation, either version 2 of the
 12+@ License, or (at your option) any later version.
 13+@
 14+@ emBIOS is distributed in the hope that it will be useful,
 15+@ but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+@ See the GNU General Public License for more details.
 18+@
 19+@ You should have received a copy of the GNU General Public License
 20+@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+@
 22+@
 23+
 24+
 25+.section .intvect,"ax",%progbits
 26+ ldr pc, =reset_handler
 27+ ldr pc, =undef_instr_handler
 28+ ldr pc, =syscall_handler
 29+ ldr pc, =prefetch_abort_handler
 30+ ldr pc, =data_abort_handler
 31+ ldr pc, =reserved_handler
 32+ ldr pc, =irq_handler
 33+ ldr pc, =fiq_handler
 34+.ltorg
 35+
 36+
 37+.section .initcode,"ax",%progbits
 38+.global _start
 39+_start:
 40+ ldr r0, =_sramsource
 41+ ldr r1, =_sramstart
 42+ ldr r2, =_sramend
 43+.copysram:
 44+ cmp r2, r1
 45+ ldrhi r3, [r0], #4
 46+ strhi r3, [r1], #4
 47+ bhi .copysram
 48+ ldr r0, =_sdramsource
 49+ ldr r1, =_sdramstart
 50+ ldr r2, =_sdramend
 51+.copysdram:
 52+ cmp r2, r1
 53+ ldrhi r3, [r0], #4
 54+ strhi r3, [r1], #4
 55+ bhi .copysdram
 56+ ldr r0, =_initbssstart
 57+ ldr r1, =_initbssend
 58+ mov r2, #0
 59+.clearinitbss:
 60+ cmp r1, r0
 61+ strhi r2, [r0], #4
 62+ bhi .clearinitbss
 63+ ldr r0, =_ibssstart
 64+ ldr r1, =_ibssend
 65+.clearibss:
 66+ cmp r1, r0
 67+ strhi r2, [r0], #4
 68+ bhi .clearibss
 69+ ldr r0, =_bssstart
 70+ ldr r1, =_bssend
 71+.clearbss:
 72+ cmp r1, r0
 73+ strhi r2, [r0], #4
 74+ bhi .clearbss
 75+ ldr r1, =0x38200000
 76+ ldr r0, [r1]
 77+ orr r0, r0, #1
 78+ bic r0, r0, #0x10000
 79+ str r0, [r1]
 80+ mov r0, #0
 81+ mcr p15, 0, r0,c7,c5,0
 82+ msr cpsr_c, #0xd2
 83+ ldr sp, =_irqstackend
 84+ msr cpsr_c, #0xd7
 85+ ldr sp, =_abortstackend
 86+ msr cpsr_c, #0xdb
 87+ ldr sp, =_abortstackend
 88+ msr cpsr_c, #0xd3
 89+ ldr sp, =_initstackend
 90+ bl init
 91+ b main
 92+.ltorg
 93+
 94+
 95+.section .icode, "ax", %progbits
 96+.align 2
 97+.global reset
 98+.global hang
 99+.type reset, %function
 100+.type hang, %function
 101+reset:
 102+ msr cpsr_c, #0xd3
 103+ mov r0, #0x110000
 104+ add r0, r0, #0xff
 105+ add r1, r0, #0xa00
 106+ mov r2, #0x3c800000
 107+ str r1, [r2]
 108+ mov r1, #0xff0
 109+ str r1, [r2,#4]
 110+ str r0, [r2]
 111+hang:
 112+ b hang
 113+.size reset, .-reset
 114+.size hang, .-hang
 115+
 116+.type reset_handler, %function
 117+reset_handler:
 118+ adr r0, reset_text
 119+ b panic
 120+reset_text:
 121+ .ascii "Hit reset vector!\0"
 122+.size reset_handler, .-reset_handler
 123+
 124+.type undef_instr_handler, %function
 125+undef_instr_handler:
 126+ adr r0, undef_instr_text
 127+ sub r0, lr, #4
 128+ b panicf
 129+.size undef_instr_handler, .-undef_instr_handler
 130+
 131+.type prefetch_abort_handler, %function
 132+prefetch_abort_handler:
 133+ adr r0, prefetch_abort_text
 134+ sub r0, lr, #4
 135+ b panicf
 136+.size prefetch_abort_handler, .-prefetch_abort_handler
 137+
 138+.type data_abort_handler, %function
 139+data_abort_handler:
 140+ adr r0, data_abort_text
 141+ sub r0, lr, #4
 142+ b panicf
 143+.size data_abort_handler, .-data_abort_handler
 144+
 145+.type reserved_handler, %function
 146+reserved_handler:
 147+ adr r0, reserved_text
 148+ b panic
 149+.size reserved_handler, .-reserved_handler
 150+
 151+.type fiq_handler, %function
 152+fiq_handler:
 153+ adr r0, fiq_text
 154+ b panic
 155+.size fiq_handler, .-fiq_handler
 156+
 157+.type irq_handler, %function
 158+irq_handler:
 159+ adr r0, irq_text
 160+ b panic
 161+.size irq_handler, .-irq_handler
 162+
 163+.type syscall_handler, %function
 164+syscall_handler:
 165+ adr r0, syscall_text
 166+ b panic
 167+.size syscall_handler, .-syscall_handler
 168+
 169+undef_instr_text:
 170+ .ascii "Undefined instruction at %08X!\0"
 171+
 172+prefetch_abort_text:
 173+ .ascii "Prefetch abort at %08X!\0"
 174+
 175+data_abort_text:
 176+ .ascii "Data abort at %08X!\0"
 177+
 178+reserved_text:
 179+ .ascii "Hit reserved exception handler!\0"
 180+
 181+fiq_text:
 182+ .ascii "Unhandled FIQ!\0"
 183+
 184+irq_text:
 185+ .ascii "Unhandled IRQ!\0"
 186+
 187+syscall_text:
 188+ .ascii "Unhandled syscall!\0"
Index: embios/branches/4g_compat/target/ipodnano2g/target.h
@@ -0,0 +1,34 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __TARGET_H__
 26+#define __TARGET_H__
 27+
 28+
 29+#include "s5l8701.h"
 30+
 31+
 32+#define ARM_ARCH 4
 33+
 34+
 35+#endif
Index: embios/branches/4g_compat/target/ipodnano2g/i2c.S
@@ -0,0 +1,135 @@
 2+@
 3+@
 4+@ Copyright 2010 TheSeven
 5+@
 6+@
 7+@ This file is part of emBIOS.
 8+@
 9+@ emBIOS is free software: you can redistribute it and/or
 10+@ modify it under the terms of the GNU General Public License as
 11+@ published by the Free Software Foundation, either version 2 of the
 12+@ License, or (at your option) any later version.
 13+@
 14+@ emBIOS is distributed in the hope that it will be useful,
 15+@ but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+@ See the GNU General Public License for more details.
 18+@
 19+@ You should have received a copy of the GNU General Public License
 20+@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+@
 22+@
 23+
 24+
 25+.section .icode.i2csend, "ax", %progbits
 26+.align 2
 27+.global i2csendbyte
 28+.global i2csend
 29+.type i2csendbyte, %function
 30+.type i2csend, %function
 31+i2csendbyte:
 32+ mov r3, #0
 33+@fallthrough
 34+
 35+i2csend:
 36+ stmfd sp!, {r4,lr}
 37+ mov r12, #0x3C000000
 38+ add r12, r12, #0x00900000
 39+ mov r4, #0
 40+ str r4, [r12,#0x08]
 41+ str r0, [r12,#0x0c]
 42+ mov r4, #0xf0
 43+ str r4, [r12,#0x04]
 44+ mov r4, #0xf3
 45+ str r4, [r12]
 46+ bl i2cwait
 47+ str r1, [r12,#0x0c]
 48+ str r4, [r12]
 49+ bl i2cwait
 50+ movs r3, r3
 51+ moveq r0, r2
 52+i2csend_write:
 53+ ldrne r0, [r2], #1
 54+ str r0, [r12,#0x0c]
 55+ str r4, [r12]
 56+ bl i2cwait
 57+ subs r3, r3, #1
 58+ bhi i2csend_write
 59+ mov r0, #0xd0
 60+ str r0, [r12,#0x04]
 61+ str r4, [r12]
 62+i2csend_wait:
 63+ ldr r0, [r12,#0x04]
 64+ tst r0, #0x20
 65+ bne i2csend_wait
 66+ ldmfd sp!, {r4,pc}
 67+.size i2csendbyte, .-i2csendbyte
 68+.size i2csend, .-i2csend
 69+
 70+
 71+.section .icode.i2crecv, "ax", %progbits
 72+.align 2
 73+.global i2crecvbyte
 74+.global i2crecv
 75+.type i2crecvbyte, %function
 76+.type i2crecv, %function
 77+i2crecvbyte:
 78+ mov r2, #0
 79+ mov r3, #1
 80+@fallthrough
 81+
 82+i2crecv:
 83+ stmfd sp!, {r0,r4,lr}
 84+ mov r12, #0x3C000000
 85+ add r12, r12, #0x00900000
 86+ mov r4, #0
 87+ str r4, [r12,#0x08]
 88+ str r0, [r12,#0x0c]
 89+ mov r4, #0xf0
 90+ str r4, [r12,#0x04]
 91+ mov r4, #0xf3
 92+ str r4, [r12]
 93+ bl i2cwait
 94+ str r1, [r12,#0x0c]
 95+ str r4, [r12]
 96+ bl i2cwait
 97+ ldr r0, [sp]
 98+ orr r0, r0, #1
 99+ str r1, [r12,#0x0c]
 100+ mov r0, #0xb0
 101+ str r0, [r12,#0x04]
 102+ str r4, [r12]
 103+ bl i2cwait
 104+i2crecv_read:
 105+ subs r3, r3, #1
 106+ moveq r4, #0x73
 107+ str r4, [r12]
 108+ bl i2cwait
 109+ ldr r0, [r12,#0x0c]
 110+ movs r2, r2
 111+ strne r0, [r2], #1
 112+ movs r3, r3
 113+ bne i2crecv_read
 114+ mov r1, #0x90
 115+ str r1, [r12,#0x04]
 116+ mov r1, #0xf3
 117+ str r1, [r12]
 118+i2crecv_wait:
 119+ ldr r1, [r12,#0x04]
 120+ tst r1, #0x20
 121+ bne i2crecv_wait
 122+ ldmfd sp!, {r0,r4,pc}
 123+.size i2crecvbyte, .-i2crecvbyte
 124+.size i2crecv, .-i2crecv
 125+
 126+
 127+.section .icode.i2cwait, "ax", %progbits
 128+.align 2
 129+.global i2cwait
 130+.type i2cwait, %function
 131+i2cwait:
 132+ ldr r0, [r12]
 133+ tst r0, #0x10
 134+ beq i2cwait
 135+ mov pc, lr
 136+.size i2cwait, .-i2cwait
Index: embios/branches/4g_compat/drawing.h
@@ -0,0 +1,39 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __DRAWING_H__
 26+#define __DRAWING_H__
 27+
 28+
 29+#include "global.h"
 30+
 31+
 32+#define FONT_WIDTH 6
 33+#define FONT_HEIGHT 8
 34+
 35+
 36+void rendertext(void* buffer, int fgcol, int bgcol, char* text, int stride);
 37+void renderbmp(void* buffer, void* bitmap, int stride);
 38+
 39+
 40+#endif
Index: embios/branches/4g_compat/drawing.S
@@ -0,0 +1,230 @@
 2+@
 3+@
 4+@ Copyright 2010 TheSeven
 5+@
 6+@
 7+@ This file is part of emBIOS.
 8+@
 9+@ emBIOS is free software: you can redistribute it and/or
 10+@ modify it under the terms of the GNU General Public License as
 11+@ published by the Free Software Foundation, either version 2 of the
 12+@ License, or (at your option) any later version.
 13+@
 14+@ emBIOS is distributed in the hope that it will be useful,
 15+@ but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+@ See the GNU General Public License for more details.
 18+@
 19+@ You should have received a copy of the GNU General Public License
 20+@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+@
 22+@
 23+
 24+
 25+.section .icode.renderbmp, "ax", %progbits
 26+.align 2
 27+.global renderbmp
 28+.type renderbmp, %function
 29+renderbmp:
 30+ ldrh r2, [r1]
 31+ sub r2, r2, #0x4d00
 32+ subs r2, r2, #0x42
 33+ movne pc, lr
 34+ stmfd sp!, {r4,lr}
 35+ ldrh r2, [r1,#18]
 36+ ldrh r12, [r1,#20]
 37+ orr r2, r2, r12,lsl#16
 38+ ldrh r4, [r1,#22]
 39+ ldrh r12, [r1,#24]
 40+ orr r4, r4, r12,lsl#16
 41+ ldrh lr, [r1,#10]
 42+ ldrh r12, [r1,#12]
 43+ orr lr, lr, r12,lsl#16
 44+ add r1, r1, lr
 45+ mov r12, #352
 46+ mul lr, r12, r4
 47+ add r0, r0, lr
 48+renderbmp_row:
 49+ mov r12, r2
 50+ sub r0, r0, r3
 51+renderbmp_pixel:
 52+ ldrb lr, [r1,#1]
 53+ strb lr, [r0], #1
 54+ ldrb lr, [r1], #2
 55+ strb lr, [r0], #1
 56+ subs r12, r12, #1
 57+ bne renderbmp_pixel
 58+ tst r2, #1
 59+ addne r1, r1, #2
 60+ sub r0, r0, r2,lsl#1
 61+ subs r4, r4, #1
 62+ bne renderbmp_row
 63+ ldmfd sp!, {r4,pc}
 64+.size renderbmp, .-renderbmp
 65+
 66+
 67+.section .icode.renderchar, "ax", %progbits
 68+.align 2
 69+.global renderchar
 70+.type renderchar, %function
 71+renderchar:
 72+ stmfd sp!, {r4-r7,lr}
 73+ ldr r7, [sp,#0x14]
 74+ cmn r2, #1
 75+ beq renderchar_nobg
 76+ mov r6, r0
 77+ mov r4, #8
 78+ mov lr, r2,lsr#16
 79+ sub lr, lr, #0xff00
 80+ subs lr, lr, #0xff
 81+ bne renderchar_opaquerow
 82+ mov r12, r2,lsl#16
 83+ mov r12, r12,lsr#16
 84+renderchar_blendrow:
 85+ mov r5, #6
 86+renderchar_blendcol:
 87+ ldrh lr, [r6]
 88+ tst lr, #1
 89+ orrne lr, lr, #0x10000
 90+ mov lr, lr,lsr#1
 91+ bic lr, lr, #0x1000
 92+ bic lr, lr, #0x84
 93+ add lr, lr, r12
 94+ strh lr, [r6], #2
 95+ subs r5, r5, #1
 96+ bne renderchar_blendcol
 97+ add r6, r6, r7
 98+ sub r6, r6, #12
 99+ subs r4, r4, #1
 100+ bne renderchar_blendrow
 101+ b renderchar_nobg
 102+renderchar_opaquerow:
 103+ mov r5, #6
 104+renderchar_opaquecol:
 105+ strh r2, [r6], #2
 106+ subs r5, r5, #1
 107+ bne renderchar_opaquecol
 108+ add r6, r6, r7
 109+ sub r6, r6, #12
 110+ subs r4, r4, #1
 111+ bne renderchar_opaquerow
 112+renderchar_nobg:
 113+ adr r5, renderchar_font
 114+ sub r3, r3, #0x20
 115+ cmp r3, #0x5f
 116+ addcc r5, r3,lsl#2
 117+ addcc r5, r3
 118+ mov r3, #5
 119+renderchar_col:
 120+ mov r6, r0
 121+ ldrb r4, [r5], #1
 122+renderchar_row:
 123+ tst r4, #1
 124+ strneh r1, [r6]
 125+ add r6, r6, r7
 126+ movs r4, r4,lsr#1
 127+ bne renderchar_row
 128+ add r0, r0, #2
 129+ subs r3, r3, #1
 130+ bne renderchar_col
 131+ add r0, r0, #2
 132+ ldmfd sp!, {r4-r7,pc}
 133+
 134+renderchar_font:
 135+ .byte 0, 0, 0, 0, 0
 136+ .byte 0, 0, 95, 0, 0
 137+ .byte 0, 7, 0, 7, 0
 138+ .byte 20, 127, 20, 127, 20
 139+ .byte 36, 42, 127, 42, 18
 140+ .byte 35, 19, 8, 100, 98
 141+ .byte 54, 73, 85, 34, 80
 142+ .byte 5, 3, 0, 0, 0
 143+ .byte 28, 34, 65, 0, 0
 144+ .byte 0, 0, 65, 34, 28
 145+ .byte 20, 8, 62, 8, 20
 146+ .byte 8, 8, 62, 8, 8
 147+ .byte 0, -96, 96, 0, 0
 148+ .byte 8, 8, 8, 8, 8
 149+ .byte 0, 96, 96, 0, 0
 150+ .byte 32, 16, 8, 4, 2
 151+ .byte 62, 81, 73, 69, 62
 152+ .byte 0, 66, 127, 64, 0
 153+ .byte 66, 97, 81, 73, 70
 154+ .byte 33, 65, 69, 75, 49
 155+ .byte 24, 20, 18, 127, 16
 156+ .byte 39, 69, 69, 69, 57
 157+ .byte 60, 74, 73, 73, 48
 158+ .byte 1, 113, 9, 5, 3
 159+ .byte 54, 73, 73, 73, 54
 160+ .byte 6, 73, 73, 41, 30
 161+ .byte 0, 54, 54, 0, 0
 162+ .byte 0, 86, 54, 0, 0
 163+ .byte 8, 20, 34, 65, 0
 164+ .byte 20, 20, 20, 20, 20
 165+ .byte 0, 65, 34, 20, 8
 166+ .byte 2, 1, 81, 9, 6
 167+ .byte 50, 73, 121, 65, 62
 168+ .byte 124, 18, 17, 18, 124
 169+ .byte 127, 73, 73, 73, 62
 170+ .byte 62, 65, 65, 65, 34
 171+ .byte 127, 65, 65, 34, 28
 172+ .byte 127, 73, 73, 73, 65
 173+ .byte 127, 9, 9, 9, 1
 174+ .byte 62, 65, 73, 73, 58
 175+ .byte 127, 8, 8, 8, 127
 176+ .byte 0, 65, 127, 65, 0
 177+ .byte 32, 64, 65, 63, 1
 178+ .byte 127, 8, 20, 34, 65
 179+ .byte 127, 64, 64, 64, 64
 180+ .byte 127, 2, 12, 2, 127
 181+ .byte 127, 4, 8, 16, 127
 182+ .byte 62, 65, 65, 65, 62
 183+ .byte 127, 9, 9, 9, 6
 184+ .byte 62, 65, 81, 33, 94
 185+ .byte 127, 9, 25, 41, 70
 186+ .byte 38, 73, 73, 73, 50
 187+ .byte 1, 1, 127, 1, 1
 188+ .byte 63, 64, 64, 64, 63
 189+ .byte 31, 32, 64, 32, 31
 190+ .byte 127, 32, 24, 32, 127
 191+ .byte 99, 20, 8, 20, 99
 192+ .byte 3, 4, 120, 4, 3
 193+ .byte 97, 81, 73, 69, 67
 194+ .byte 0, 127, 65, 65, 0
 195+ .byte 2, 4, 8, 16, 32
 196+ .byte 0, 65, 65, 127, 0
 197+ .byte 4, 2, 1, 2, 4
 198+ .byte 64, 64, 64, 64, 64
 199+ .byte 1, 2, 4, 0, 0
 200+ .byte 32, 84, 84, 84, 120
 201+ .byte 127, 68, 68, 68, 56
 202+ .byte 56, 68, 68, 68, 40
 203+ .byte 56, 68, 68, 68, 127
 204+ .byte 56, 84, 84, 84, 24
 205+ .byte 8, 126, 9, 1, 2
 206+ .byte 8, 84, 84, 84, 60
 207+ .byte 127, 4, 4, 4, 120
 208+ .byte 0, 68, 125, 64, 0
 209+ .byte 32, 64, 64, 61, 0
 210+ .byte 127, 16, 40, 68, 0
 211+ .byte 0, 65, 127, 64, 0
 212+ .byte 124, 4, 24, 4, 120
 213+ .byte 124, 8, 4, 4, 120
 214+ .byte 56, 68, 68, 68, 56
 215+ .byte 124, 20, 20, 20, 24
 216+ .byte 8, 20, 20, 20, 124
 217+ .byte 124, 8, 4, 4, 8
 218+ .byte 72, 84, 84, 84, 32
 219+ .byte 4, 63, 68, 64, 32
 220+ .byte 60, 64, 64, 32, 124
 221+ .byte 28, 32, 64, 32, 28
 222+ .byte 60, 64, 56, 64, 60
 223+ .byte 68, 40, 16, 40, 68
 224+ .byte 12, 80, 80, 80, 60
 225+ .byte 68, 100, 84, 76, 68
 226+ .byte 0, 8, 54, 65, 0
 227+ .byte 0, 0, 119, 0, 0
 228+ .byte 0, 65, 54, 8, 0
 229+ .byte 2, 1, 2, 4, 2
 230+.align 2
 231+.size renderchar, .-renderchar
Index: embios/branches/4g_compat/lcdconsole.c
@@ -0,0 +1,90 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+#include "lcdconsole.h"
 27+#include "util.h"
 28+
 29+
 30+#define OFFSETX LCDCONSOLE_OFFSETX
 31+#define OFFSETY LCDCONSOLE_OFFSETY
 32+#define PIXELBYTES (LCD_BYTESPERPIXEL)
 33+#define LINEBYTES (LCD_WIDTH * PIXELBYTES)
 34+#define COLBYTES (FONT_WIDTH * PIXELBYTES)
 35+#define ROWBYTES (FONT_HEIGHT * LINEBYTES)
 36+#define OFFSETBYTES (LINEBYTES * OFFSETY + PIXELBYTES * OFFSETX)
 37+
 38+
 39+static unsigned char framebuf[LCD_FRAMEBUFSIZE];
 40+static unsigned int current_row;
 41+static unsigned int current_col;
 42+
 43+
 44+void lcdconsole_init()
 45+{
 46+ memset(framebuf, -1, sizeof(framebuf));
 47+ current_row = 0;
 48+ current_col = -1;
 49+}
 50+
 51+void lcdconsole_putc(char string, int fgcolor, int bgcolor)
 52+{
 53+ if (string == '\r') return;
 54+ current_col++;
 55+ if (string == '\n')
 56+ {
 57+ current_col = -1;
 58+ current_row++;
 59+ return;
 60+ }
 61+ if (string == '\t')
 62+ {
 63+ current_col |= 3;
 64+ return;
 65+ }
 66+ if (current_col >= LCDCONSOLE_COLS)
 67+ {
 68+ current_col = 0;
 69+ current_row++;
 70+ }
 71+ if (current_row >= LCDCONSOLE_ROWS)
 72+ {
 73+ int offset = current_row - LCDCONSOLE_ROWS + 1;
 74+ memcpy(framebuf, &framebuf[ROWBYTES * offset], ROWBYTES * offset);
 75+ memset(&framebuf[sizeof(framebuf) - ROWBYTES * offset],
 76+ -1, ROWBYTES * offset);
 77+ }
 78+ renderchar(&framebuf[OFFSETBYTES + ROWBYTES * current_row
 79+ + COLBYTES * current_col],
 80+ fgcolor, bgcolor, string, LINEBYTES);
 81+}
 82+
 83+void lcdconsole_puts(const char* string, int fgcolor, int bgcolor)
 84+{
 85+ while (*string) lcdconsole_putc(*string++, fgcolor, bgcolor);
 86+}
 87+
 88+void lcdconsole_update()
 89+{
 90+ displaylcd(0, LCD_WIDTH - 1, 0, LCD_HEIGHT - 1, framebuf, 0);
 91+}
Index: embios/branches/4g_compat/arm-support.S
@@ -0,0 +1,706 @@
 2+/***************************************************************************
 3+ * __________ __ ___.
 4+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
 5+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
 6+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
 7+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
 8+ * \/ \/ \/ \/ \/
 9+ * $Id$
 10+ *
 11+ * Copyright (C) 2008 by Jens Arnold
 12+ * Copyright (C) 2009 by Andrew Mahone
 13+ *
 14+ * Optimised replacements for libgcc functions
 15+ *
 16+ * Based on: libgcc routines for ARM cpu, additional algorithms from ARM System
 17+ * Developer's Guide
 18+ * Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
 19+ * Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
 20+ * Free Software Foundation, Inc.
 21+ *
 22+ * This program is free software; you can redistribute it and/or
 23+ * modify it under the terms of the GNU General Public License
 24+ * as published by the Free Software Foundation; either version 2
 25+ * of the License, or (at your option) any later version.
 26+ *
 27+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 28+ * KIND, either express or implied.
 29+ *
 30+ ****************************************************************************/
 31+
 32+#define ASM_FILE
 33+#include "global.h"
 34+
 35+.macro ARM_SDIV32_PRE numerator, divisor, sign
 36+ /* sign[31] = divisor sign */
 37+ ands \sign, \divisor, #1<<31
 38+ rsbeq \divisor, \divisor, #0
 39+ /* sign[31] = result sign, sign[0:30], C = numerator sign */
 40+ eors \sign, \sign, \numerator, asr #32
 41+ rsbcs \numerator, \numerator, #0
 42+.endm
 43+
 44+.macro ARM_SDIV32_POST quotient, remainder, sign
 45+ movs \sign, \sign, lsl #1
 46+.ifnc "", "\quotient"
 47+ rsbcs \quotient, \quotient, #0
 48+.endif
 49+.ifnc "", "\remainder"
 50+ rsbmi \remainder, \remainder, #0
 51+.endif
 52+.endm
 53+
 54+#if ARM_ARCH < 5
 55+.macro ARMV4_UDIV32_BODY numerator, divisor, quotient, remainder, tmp, bits, div0label, return
 56+.ifnc "", "\div0label"
 57+ rsbs \divisor, \divisor, #0
 58+ beq \div0label
 59+.else
 60+ rsb \divisor, \divisor, #0
 61+.endif
 62+ /* This SWAR divider requires a numerator less than 1<<31, because it must
 63+ be able to shift the remainder left at each step without shifting out
 64+ topmost bit. Since a shift might be needed for the aligned remainder to
 65+ exceed the divisor, the topmost bit must be unset at the start to avoid
 66+ this overflow case. The original numerator is saved so that the result
 67+ can be corrected after the reduced division completes. */
 68+ cmn \numerator, \divisor
 69+.ifc "", "\quotient"
 70+.ifc "\numerator", "\remainder"
 71+.if \return
 72+ bxcc lr
 73+.else
 74+ b 99f
 75+.endif
 76+.else
 77+ bcc 20f
 78+.endif
 79+.else
 80+ bcc 20f
 81+.endif
 82+ movs \tmp, \numerator
 83+ movmi \numerator, \numerator, lsr #1
 84+ mov \bits, #30
 85+.set shift, 16
 86+.rept 5
 87+ cmn \divisor, \numerator, lsr #shift
 88+ subcs \bits, \bits, #shift
 89+ movcs \divisor, \divisor, lsl #shift
 90+.set shift, shift >> 1
 91+.endr
 92+ adds \numerator, \numerator, \divisor
 93+ subcc \numerator, \numerator, \divisor
 94+ add pc, pc, \bits, lsl #3
 95+ nop
 96+.rept 30
 97+ adcs \numerator, \divisor, \numerator, lsl #1
 98+ subcc \numerator, \numerator, \divisor
 99+.endr
 100+ adc \numerator, \numerator, \numerator
 101+ movs \tmp, \tmp, asr #1
 102+ rsb \bits, \bits, #31
 103+ bmi 10f
 104+.ifc "", "\quotient"
 105+ mov \remainder, \numerator, lsr \bits
 106+.else
 107+.ifc "", "\remainder"
 108+ mov \divisor, \numerator, lsr \bits
 109+ eor \quotient, \numerator, \divisor, lsl \bits
 110+.else
 111+ mov \remainder, \numerator, lsr \bits
 112+ eor \quotient, \numerator, \remainder, lsl \bits
 113+.endif
 114+.endif
 115+.ifne \return
 116+ bx lr
 117+.else
 118+ b 99f
 119+.endif
 120+10:
 121+ mov \tmp, \numerator, lsr \bits
 122+ eor \numerator, \numerator, \tmp, lsl \bits
 123+ sub \bits, \bits, #1
 124+ adc \tmp, \tmp, \tmp
 125+ adds \tmp, \tmp, \divisor, asr \bits
 126+.ifnc "", "\quotient"
 127+ adc \quotient, \numerator, \numerator
 128+.endif
 129+.ifnc "", "\remainder"
 130+ subcc \remainder, \tmp, \divisor, asr \bits
 131+ movcs \remainder, \tmp
 132+.endif
 133+.ifne \return
 134+ bx lr
 135+.else
 136+ b 99f
 137+.endif
 138+20:
 139+.ifnc "", "\remainder"
 140+.ifnc "\remainder", "\numerator"
 141+ mov \remainder, \numerator
 142+.endif
 143+.endif
 144+.ifnc "", "\quotient"
 145+ mov \quotient, #0
 146+.endif
 147+.ifne \return
 148+ bx lr
 149+.else
 150+99:
 151+.endif
 152+.endm
 153+
 154+.macro ARMV4_SDIV32_BODY numerator, divisor, quotient, remainder, bits, sign, div0label, return
 155+ /* When this is wrapped for signed division, the wrapper code will handle
 156+ inverting the divisor, and also the zero divisor test. */
 157+ ARM_SDIV32_PRE \numerator, \divisor, \sign
 158+.ifnc "", "\div0label"
 159+ tst \divisor, \divisor
 160+ beq \div0label
 161+.endif
 162+ /* This SWAR divider requires a numerator less than 1<<31, because it must
 163+ be able to shift the remainder left at each step without shifting out
 164+ topmost bit. With signed inputs, whose absolute value may not exceed
 165+ 1<<31,this may be accomplished simply by subtracting the divisor before
 166+ beginning division, and adding 1 to the quotient. */
 167+ adds \numerator, \numerator, \divisor
 168+ bcc 20f
 169+ mov \bits, #30
 170+.set shift, 16
 171+.rept 5
 172+ cmn \divisor, \numerator, lsr #shift
 173+ subcs \bits, \bits, #shift
 174+ movcs \divisor, \divisor, lsl #shift
 175+.set shift, shift >> 1
 176+.endr
 177+ adds \numerator, \numerator, \divisor
 178+ subcc \numerator, \numerator, \divisor
 179+ add pc, pc, \bits, lsl #3
 180+ nop
 181+.rept 30
 182+ adcs \numerator, \divisor, \numerator, lsl #1
 183+ subcc \numerator, \numerator, \divisor
 184+.endr
 185+ rsb \bits, \bits, #31
 186+ adc \numerator, \numerator, \numerator
 187+.ifc "", "\quotient"
 188+ mov \remainder, \numerator, lsr \bits
 189+.else
 190+.ifc "", "\remainder"
 191+ mov \divisor, \numerator, lsr \bits
 192+ add \numerator, \numerator, #1
 193+ sub \quotient, \numerator, \divisor, lsl \bits
 194+.else
 195+ mov \remainder, \numerator, lsr \bits
 196+ add \numerator, \numerator, #1
 197+ sub \quotient, \numerator, \remainder, lsl \bits
 198+.endif
 199+.endif
 200+.ifne \return
 201+ ARM_SDIV32_POST \quotient, \remainder, \sign
 202+ bx lr
 203+.else
 204+ b 99f
 205+.endif
 206+20:
 207+.ifnc "", "\remainder"
 208+ sub \remainder, \numerator, \divisor
 209+.endif
 210+.ifnc "", "\quotient"
 211+ mov \quotient, #0
 212+.endif
 213+.ifne \return
 214+ ARM_SDIV32_POST "", \remainder, \sign
 215+ bx lr
 216+.else
 217+99:
 218+ ARM_SDIV32_POST \quotient, \remainder, \sign
 219+.endif
 220+.endm
 221+
 222+#else
 223+.macro ARMV5_UDIV32_BODY numerator, divisor, quotient, remainder, bits, inv, neg, div0label, return
 224+ cmp \numerator, \divisor
 225+ clz \bits, \divisor
 226+ bcc 30f
 227+ mov \inv, \divisor, lsl \bits
 228+ add \neg, pc, \inv, lsr #25
 229+ /* Test whether divisor is 2^N */
 230+ cmp \inv, #1<<31
 231+ /* Load approximate reciprocal */
 232+ ldrhib \inv, [\neg, #.L_udiv_est_table-.-64]
 233+ bls 20f
 234+ subs \bits, \bits, #7
 235+ rsb \neg, \divisor, #0
 236+ /* Scale approximate reciprocal, or else branch to large-divisor path */
 237+ movpl \divisor, \inv, lsl \bits
 238+ bmi 10f
 239+ /* Newton-Raphson iteration to improve reciprocal accuracy */
 240+ mul \inv, \divisor, \neg
 241+ smlawt \divisor, \divisor, \inv, \divisor
 242+ mul \inv, \divisor, \neg
 243+ /* Complete N-R math and produce approximate quotient. Use smmla/smmul on
 244+ ARMv6. */
 245+#if ARM_ARCH >= 6
 246+ tst \numerator, \numerator
 247+ smmla \divisor, \divisor, \inv, \divisor
 248+ /* Branch to large-numerator handler, or else use smmul if sign bit is not
 249+ set. This wins on average with random numerators, and should be no
 250+ slower than using umull for small numerator, even if prediction fails.
 251+ */
 252+ bmi 40f
 253+ smmul \inv, \numerator, \divisor
 254+#else
 255+ /* ARMv5e lacks smmul, so always uses umull. */
 256+ mov \bits, #0
 257+ smlal \bits, \divisor, \inv, \divisor
 258+ umull \bits, \inv, \numerator, \divisor
 259+#endif
 260+ /* Calculate remainder and correct result. */
 261+ add \numerator, \numerator, \neg
 262+.ifnc "", "\remainder"
 263+ mla \remainder, \inv, \neg, \numerator
 264+.ifnc "", "\quotient"
 265+ mov \quotient, \inv
 266+ cmn \remainder, \neg
 267+ subcs \remainder, \remainder, \neg
 268+ addpl \remainder, \remainder, \neg, lsl #1
 269+ addcc \quotient, \quotient, #1
 270+ addpl \quotient, \quotient, #2
 271+.else
 272+ cmn \remainder, \neg
 273+ subcs \remainder, \remainder, \neg
 274+ addpl \remainder, \remainder, \neg, lsl #1
 275+.endif
 276+.else
 277+ mla \divisor, \inv, \neg, \numerator
 278+ mov \quotient, \inv
 279+ cmn \divisor, \neg
 280+ addcc \quotient, \quotient, #1
 281+ addpl \quotient, \quotient, #2
 282+.endif
 283+.if \return
 284+ bx lr
 285+.else
 286+ b 99f
 287+.endif
 288+10:
 289+ /* Very large divisors can be handled without further improving the
 290+ reciprocal. First the reciprocal must be reduced to ensure that it
 291+ underestimates the correct value. */
 292+ rsb \bits, \bits, #0
 293+ sub \inv, \inv, #4
 294+ mov \divisor, \inv, lsr \bits
 295+ /* Calculate approximate quotient and remainder */
 296+ umull \bits, \inv, \numerator, \divisor
 297+ /* Correct quotient and remainder */
 298+.ifnc "", "\remainder"
 299+ mla \remainder, \inv, \neg, \numerator
 300+.ifnc "", "\quotient"
 301+ mov \quotient, \inv
 302+ cmn \neg, \remainder, lsr #1
 303+ addcs \remainder, \remainder, \neg, lsl #1
 304+ addcs \quotient, \quotient, #2
 305+ cmn \neg, \remainder
 306+ addcs \remainder, \remainder, \neg
 307+ addcs \quotient, \quotient, #1
 308+.else
 309+ cmn \neg, \remainder, lsr #1
 310+ addcs \remainder, \remainder, \neg, lsl #1
 311+ cmn \neg, \remainder
 312+ addcs \remainder, \remainder, \neg
 313+.endif
 314+.else
 315+ mla \divisor, \inv, \neg, \numerator
 316+ mov \quotient, \inv
 317+ cmn \neg, \divisor, lsr #1
 318+ addcs \divisor, \divisor, \neg, lsl #1
 319+ addcs \quotient, \quotient, #2
 320+ cmn \neg, \divisor
 321+ addcs \quotient, \quotient, #1
 322+.endif
 323+.if \return
 324+ bx lr
 325+.else
 326+ b 99f
 327+.endif
 328+20:
 329+ /* Handle division by powers of two by shifting right. Mod is handled
 330+ by using divisor-1 as a bitmask. */
 331+.ifnc "", "\remainder"
 332+.ifnc "", "\div0label"
 333+ bne \div0label
 334+.endif
 335+.ifnc "", "\quotient"
 336+ sub \divisor, \divisor, #1
 337+ rsb \bits, \bits, #31
 338+ and \remainder, \numerator, \divisor
 339+ mov \quotient, \numerator, lsr \bits
 340+.else
 341+ sub \divisor, \divisor, #1
 342+ and \remainder, \numerator, \divisor
 343+.endif
 344+.else
 345+ rsb \bits, \bits, #31
 346+.ifnc "", "\div0label"
 347+ bne \div0label
 348+.endif
 349+ mov \quotient, \numerator, lsr \bits
 350+.endif
 351+.if \return
 352+ bx lr
 353+.else
 354+ b 99f
 355+.endif
 356+30:
 357+ /* Handle numerator < divisor - quotient is zero, remainder is numerator,
 358+ which must be restored to its original value on ARMv6. */
 359+.ifnc "", "\remainder"
 360+ mov \remainder, \numerator
 361+.endif
 362+.ifnc "", "\quotient"
 363+ mov \quotient, #0
 364+.endif
 365+.if \return
 366+ bx lr
 367+.endif
 368+#if ARM_ARCH >= 6
 369+40:
 370+ /* Handle large (sign bit set) numerators. Works exactly as the ARMv5e code
 371+ above 10:. */
 372+ umull \bits, \inv, \numerator, \divisor
 373+ add \numerator, \numerator, \neg
 374+.ifnc "", "\remainder"
 375+ mla \remainder, \inv, \neg, \numerator
 376+.ifnc "", "\quotient"
 377+ mla \remainder, \inv, \neg, \numerator
 378+ mov \quotient, \inv
 379+ cmn \remainder, \neg
 380+ subcs \remainder, \remainder, \neg
 381+ addpl \remainder, \remainder, \neg, lsl #1
 382+ addcc \quotient, \quotient, #1
 383+ addpl \quotient, \quotient, #2
 384+.else
 385+ cmn \remainder, \neg
 386+ subcs \remainder, \remainder, \neg
 387+ addpl \remainder, \remainder, \neg, lsl #1
 388+.endif
 389+.else
 390+ mla \divisor, \inv, \neg, \numerator
 391+ mov \quotient, \inv
 392+ cmn \divisor, \neg
 393+ addcc \quotient, \quotient, #1
 394+ addpl \quotient, \quotient, #2
 395+.endif
 396+.if \return
 397+ bx lr
 398+.else
 399+ b 99f
 400+.endif
 401+#endif
 402+99:
 403+.endm
 404+
 405+.macro ARMV5_SDIV32_BODY numerator, divisor, quotient, remainder, bits, inv, neg, sign, div0label, return
 406+ /* sign[31] = divisor sign */
 407+ ands \sign, \divisor, #1<<31
 408+ rsbne \divisor, \divisor, #0
 409+ /* sign[31] = result sign, sign[0:30], C = numerator sign */
 410+ eors \sign, \sign, \numerator, asr #32
 411+ clz \bits, \divisor
 412+ rsbcs \numerator, \numerator, #0
 413+ /* On ARMv6, subtract divisor before performing division, which ensures
 414+ numerator sign bit is clear and smmul may be used in place of umull. The
 415+ fixup for the results can be fit entirely into existing delay slots on
 416+ the main division paths. It costs 1c in the num<div path if the
 417+ the remainder is to be produced in the numerator's register, and 1c in
 418+ the power-of-2-divisor path only if producing both remainder and
 419+ quotient. */
 420+#if ARM_ARCH >= 6
 421+ subs \numerator, \numerator, \divisor
 422+#else
 423+ cmp \numerator, \divisor
 424+#endif
 425+ movcs \inv, \divisor, lsl \bits
 426+ bcc 30f
 427+ /* Test whether divisor is 2^N */
 428+ cmp \inv, #1<<31
 429+ add \inv, pc, \inv, lsr #25
 430+ bls 20f
 431+ /* Load approximate reciprocal */
 432+ ldrb \inv, [\inv, #.L_udiv_est_table-.-64]
 433+ subs \bits, \bits, #7
 434+ rsb \neg, \divisor, #0
 435+ /* Scale approximate reciprocal, or else branch to large-divisor path */
 436+ movpl \divisor, \inv, lsl \bits
 437+ bmi 10f
 438+ /* Newton-Raphson iteration to improve reciprocal accuracy */
 439+ mul \inv, \divisor, \neg
 440+ smlawt \divisor, \divisor, \inv, \divisor
 441+ mul \inv, \divisor, \neg
 442+ /* Complete N-R math and produce approximate quotient. Use smmla/smmul on
 443+ ARMv6. */
 444+#if ARM_ARCH >= 6
 445+ smmla \divisor, \divisor, \inv, \divisor
 446+ smmul \inv, \numerator, \divisor
 447+#else
 448+ mov \bits, #0
 449+ smlal \bits, \divisor, \inv, \divisor
 450+ umull \bits, \inv, \numerator, \divisor
 451+#endif
 452+ /* Calculate remainder and correct quotient. */
 453+ add \numerator, \numerator, \neg
 454+.ifnc "", "\remainder"
 455+ mla \remainder, \inv, \neg, \numerator
 456+.ifnc "", "\quotient"
 457+#if ARM_ARCH >= 6
 458+ add \quotient, \inv, #1
 459+#else
 460+ mov \quotient, \inv
 461+#endif
 462+ cmn \remainder, \neg
 463+ subcs \remainder, \remainder, \neg
 464+ addpl \remainder, \remainder, \neg, lsl #1
 465+ addcc \quotient, \quotient, #1
 466+ addpl \quotient, \quotient, #2
 467+.else
 468+ cmn \remainder, \neg
 469+ subcs \remainder, \remainder, \neg
 470+ addpl \remainder, \remainder, \neg, lsl #1
 471+.endif
 472+.else
 473+ mla \divisor, \inv, \neg, \numerator
 474+#if ARM_ARCH >= 6
 475+ add \quotient, \inv, #1
 476+#else
 477+ mov \quotient, \inv
 478+#endif
 479+ cmn \divisor, \neg
 480+ addcc \quotient, \quotient, #1
 481+ addpl \quotient, \quotient, #2
 482+.endif
 483+ ARM_SDIV32_POST \quotient, \remainder, \sign
 484+.ifnc "", "\return"
 485+ \return
 486+.else
 487+ b 99f
 488+.endif
 489+10:
 490+ /* Very large divisors can be handled without further improving the
 491+ reciprocal. First the reciprocal must be reduced to ensure that it
 492+ underestimates the correct value. */
 493+ rsb \bits, \bits, #0
 494+ sub \inv, \inv, #4
 495+ mov \divisor, \inv, lsr \bits
 496+ /* Calculate approximate quotient and remainder */
 497+#if ARM_ARCH >= 6
 498+ smmul \inv, \numerator, \divisor
 499+#else
 500+ umull \bits, \inv, \numerator, \divisor
 501+#endif
 502+ /* Correct quotient and remainder */
 503+.ifnc "", "\remainder"
 504+ mla \remainder, \inv, \neg, \numerator
 505+.ifnc "", "\quotient"
 506+#if ARM_ARCH >= 6
 507+ add \quotient, \inv, #1
 508+#else
 509+ mov \quotient, \inv
 510+#endif
 511+ cmn \neg, \remainder, lsr #1
 512+ addcs \remainder, \remainder, \neg, lsl #1
 513+ addcs \quotient, \quotient, #2
 514+ cmn \neg, \remainder
 515+ addcs \remainder, \remainder, \neg
 516+ addcs \quotient, \quotient, #1
 517+.else
 518+ cmn \neg, \remainder, lsr #1
 519+ addcs \remainder, \remainder, \neg, lsl #1
 520+ cmn \neg, \remainder
 521+ addcs \remainder, \remainder, \neg
 522+.endif
 523+.else
 524+ mla \divisor, \inv, \neg, \numerator
 525+#if ARM_ARCH >= 6
 526+ add \quotient, \inv, #1
 527+#else
 528+ mov \quotient, \inv
 529+#endif
 530+ cmn \neg, \divisor, lsr #1
 531+ addcs \divisor, \divisor, \neg, lsl #1
 532+ addcs \quotient, \quotient, #2
 533+ cmn \neg, \divisor
 534+ addcs \quotient, \quotient, #1
 535+.endif
 536+ ARM_SDIV32_POST \quotient, \remainder, \sign
 537+.ifnc "", "\return"
 538+ \return
 539+.else
 540+ b 99f
 541+.endif
 542+20:
 543+ /* Handle division by powers of two by shifting right. Mod is handled
 544+ by using divisor-1 as a bitmask. */
 545+.ifnc "", "\div0label"
 546+ bne \div0label
 547+.endif
 548+.ifnc "", "\remainder"
 549+.ifnc "", "\quotient"
 550+ rsb \bits, \bits, #31
 551+#if ARM_ARCH >= 6
 552+ add \numerator, \numerator, \divisor
 553+#endif
 554+ sub \divisor, \divisor, #1
 555+ and \remainder, \numerator, \divisor
 556+ mov \quotient, \numerator, lsr \bits
 557+.else
 558+ sub \divisor, \divisor, #1
 559+ and \remainder, \numerator, \divisor
 560+.endif
 561+.else
 562+ rsb \bits, \bits, #31
 563+#if ARM_ARCH >= 6
 564+ add \numerator, \numerator, \divisor
 565+#endif
 566+ mov \quotient, \numerator, lsr \bits
 567+.endif
 568+ ARM_SDIV32_POST \quotient, \remainder, \sign
 569+.ifnc "", "\return"
 570+ \return
 571+.else
 572+ b 99f
 573+.endif
 574+30:
 575+ /* Handle numerator < divisor - quotient is zero, remainder is numerator,
 576+ which must be restored to its original value on ARMv6. */
 577+.ifnc "", "\remainder"
 578+#if ARM_ARCH >= 6
 579+ add \remainder, \numerator, \divisor
 580+#else
 581+.ifnc "\remainder", "\numerator"
 582+ mov \remainder, \numerator
 583+.endif
 584+#endif
 585+.endif
 586+.ifnc "", "\quotient"
 587+ mov \quotient, #0
 588+.endif
 589+.ifnc "", "\remainder"
 590+ ARM_SDIV32_POST "", \remainder, \sign
 591+.endif
 592+.ifnc "", "\return"
 593+ \return
 594+.endif
 595+99:
 596+.endm
 597+#endif
 598+
 599+ .section .text.__div0_wrap_s
 600+__div0_wrap_s:
 601+ sub sp, sp, #4
 602+ b __div0
 603+ .size __div0_wrap_s, . - __div0_wrap_s
 604+
 605+ .section .text.__div0_wrap
 606+__div0_wrap:
 607+ str lr, [sp, #-4]!
 608+ b __div0
 609+ .size __div0_wrap, . - __div0_wrap
 610+
 611+#ifndef __ARM_EABI__
 612+ .global __divsi3
 613+ .type __divsi3,%function
 614+ .global __udivsi3
 615+ .type __udivsi3,%function
 616+ .global __udivsi3
 617+ .type __udivsi3,%function
 618+#else
 619+/* The div+mod averagess a fraction of a cycle worse for signed values, and
 620+ slightly better for unsigned, so just alias div to divmod. */
 621+ .global __aeabi_uidivmod
 622+ .type __aeabi_uidivmod,%function
 623+ .global __aeabi_uidiv
 624+ .type __aeabi_uidiv,%function
 625+ .set __aeabi_uidiv,__aeabi_uidivmod
 626+ .global __aeabi_idivmod
 627+ .type __aeabi_idivmod,%function
 628+ .global __aeabi_idiv
 629+ .type __aeabi_idiv,%function
 630+ .set __aeabi_idiv,__aeabi_idivmod
 631+#endif
 632+
 633+
 634+#if ARM_ARCH < 5
 635+ .section .text.__clzsi2
 636+ .global __clzsi2
 637+ .type __clzsi2, %function
 638+
 639+__clzsi2:
 640+ orr r0, r0, r0, lsr #8
 641+ orr r0, r0, r0, lsr #4
 642+ orr r0, r0, r0, lsr #2
 643+ orr r0, r0, r0, lsr #1
 644+ bic r0, r0, r0, lsr #16
 645+ rsb r0, r0, r0, lsl #14
 646+ rsb r0, r0, r0, lsl #11
 647+ rsb r0, r0, r0, lsl #9
 648+ ldrb r0, [pc, r0, lsr #26]
 649+ bx lr
 650+ .byte 32, 20, 19, 0, 0, 18, 0, 7, 10, 17, 0, 0, 14, 0, 6, 0
 651+ .byte 0, 9, 0, 16, 0, 0, 1, 26, 0, 13, 0, 0, 24, 5, 0, 0
 652+ .byte 0, 21, 0, 8, 11, 0, 15, 0, 0, 0, 0, 2, 27, 0, 25, 0
 653+ .byte 22, 0, 12, 0, 0, 3, 28, 0, 23, 0, 4, 29, 0, 0, 30, 31
 654+ .size __clzsi2, .-__clzsi2
 655+
 656+ .section .text.__divisionhelpers
 657+#ifndef __ARM_EABI__
 658+__udivsi3:
 659+ ARMV4_UDIV32_BODY r0, r1, r0, "", r2, r3, __div0_wrap, 1
 660+ .size __udivsi3, . - __udivsi3
 661+
 662+__divsi3:
 663+ ARMV4_SDIV32_BODY r0, r1, r0, "", r2, r3, __div0_wrap, 1
 664+ .size __divsi3, . - __divsi3
 665+
 666+#else
 667+__aeabi_uidivmod:
 668+ ARMV4_UDIV32_BODY r0, r1, r0, r1, r2, r3, __div0_wrap, 1
 669+ .size __aeabi_uidivmod, . - __aeabi_uidivmo
 670+
 671+__aeabi_idivmod:
 672+ ARMV4_SDIV32_BODY r0, r1, r0, r1, r2, r3, __div0_wrap, 1
 673+ .size __aeabi_idivmod, . - __aeabi_idivmod
 674+#endif
 675+
 676+#else
 677+#ifndef __ARM_EABI__
 678+__udivsi3:
 679+ ARMV5_UDIV32_BODY r0, r1, r0, "", r2, r3, ip, __div0_wrap, 1
 680+ .size __udivsi3, . - __udivsi3
 681+
 682+__divsi3:
 683+ str lr, [sp, #-4]
 684+ ARMV5_SDIV32_BODY r0, r1, r0, "", r2, lr, ip, r3, __div0_wrap_s, "ldr pc, [sp, #-4]"
 685+ .size __divsi3, . - __divsi3
 686+
 687+#else
 688+__aeabi_uidivmod:
 689+ ARMV5_UDIV32_BODY r0, r1, r0, r1, r2, r3, ip, __div0_wrap, 1
 690+ .size __aeabi_uidivmod, . - __aeabi_uidivmo
 691+
 692+__aeabi_idivmod:
 693+ str lr, [sp, #-4]
 694+ ARMV5_SDIV32_BODY r0, r1, r0, r1, r2, lr, ip, r3, __div0_wrap_s, "ldr pc, [sp, #-4]"
 695+ .size __aeabi_idivmod, . - __aeabi_idivmod
 696+#endif
 697+
 698+.L_udiv_est_table:
 699+ .byte 0xff, 0xfc, 0xf8, 0xf4, 0xf0, 0xed, 0xea, 0xe6
 700+ .byte 0xe3, 0xe0, 0xdd, 0xda, 0xd7, 0xd4, 0xd2, 0xcf
 701+ .byte 0xcc, 0xca, 0xc7, 0xc5, 0xc3, 0xc0, 0xbe, 0xbc
 702+ .byte 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0, 0xae, 0xac
 703+ .byte 0xaa, 0xa8, 0xa7, 0xa5, 0xa3, 0xa2, 0xa0, 0x9f
 704+ .byte 0x9d, 0x9c, 0x9a, 0x99, 0x97, 0x96, 0x94, 0x93
 705+ .byte 0x92, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8a, 0x89
 706+ .byte 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81
 707+#endif
Index: embios/branches/4g_compat/panic.h
@@ -0,0 +1,35 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __PANIC_H__
 26+#define __PANIC_H__
 27+
 28+
 29+#include "global.h"
 30+
 31+
 32+void panic(const char* string) ICODE_ATTR;
 33+void panicf(const char* string, ...) ICODE_ATTR;
 34+
 35+
 36+#endif
Index: embios/branches/4g_compat/console.c
@@ -0,0 +1,89 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+#include "console.h"
 27+#include "lcdconsole.h"
 28+#include "format.h"
 29+#include <stdio.h>
 30+#include <stdarg.h>
 31+#include <stdbool.h>
 32+#include <limits.h>
 33+
 34+
 35+struct for_cprintf
 36+{
 37+ unsigned int consoles;
 38+ size_t bytes;
 39+};
 40+
 41+
 42+static int cprfunc(void* ptr, unsigned char letter)
 43+{
 44+ struct for_cprintf* pr = (struct for_cprintf*)ptr;
 45+ cputc(pr->consoles, letter);
 46+ pr->bytes++;
 47+ return true;
 48+}
 49+
 50+int cprintf(unsigned int consoles, const char* fmt, ...)
 51+{
 52+ va_list ap;
 53+ struct for_cprintf pr;
 54+
 55+ pr.consoles = consoles;
 56+ pr.bytes = 0;
 57+
 58+ va_start(ap, fmt);
 59+ format(cprfunc, &pr, fmt, ap);
 60+ va_end(ap);
 61+
 62+ return pr.bytes;
 63+}
 64+
 65+int cvprintf(unsigned int consoles, const char* fmt, va_list ap)
 66+{
 67+ struct for_cprintf pr;
 68+
 69+ pr.consoles = consoles;
 70+ pr.bytes = 0;
 71+
 72+ format(cprfunc, &pr, fmt, ap);
 73+
 74+ return pr.bytes;
 75+}
 76+
 77+void cputc(unsigned int consoles, char string)
 78+{
 79+ if (consoles & 1) lcdconsole_putc(string, 0, -1);
 80+}
 81+
 82+void cputs(unsigned int consoles, const char* string)
 83+{
 84+ if (consoles & 1) lcdconsole_puts(string, 0, -1);
 85+}
 86+
 87+void cflush(unsigned int consoles)
 88+{
 89+ if (consoles & 1) lcdconsole_update();
 90+}
Index: embios/branches/4g_compat/ucl.S
@@ -0,0 +1,135 @@
 2+/* arm_nrv2e_d8.S -- ARM decompressor for NRV2E
 3+
 4+ This file is part of the UPX executable compressor.
 5+
 6+ Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
 7+ Copyright (C) 1996-2008 Laszlo Molnar
 8+ Copyright (C) 2000-2008 John F. Reiser
 9+ All Rights Reserved.
 10+
 11+ UPX and the UCL library are free software; you can redistribute them
 12+ and/or modify them under the terms of the GNU General Public License as
 13+ published by the Free Software Foundation; either version 2 of
 14+ the License, or (at your option) any later version.
 15+
 16+ This program is distributed in the hope that it will be useful,
 17+ but WITHOUT ANY WARRANTY; without even the implied warranty of
 18+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 19+ GNU General Public License for more details.
 20+
 21+ You should have received a copy of the GNU General Public License
 22+ along with this program; see the file COPYING.
 23+ If not, write to the Free Software Foundation, Inc.,
 24+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 25+
 26+ Markus F.X.J. Oberhumer Laszlo Molnar
 27+ <markus@oberhumer.com> <ml1050@users.sourceforge.net>
 28+
 29+ John F. Reiser
 30+ <jreiser@users.sourceforge.net>
 31+*/
 32+
 33+#define src r0
 34+#define len r1 /* overlaps 'cnt' */
 35+#define dst r2
 36+#define tmp r3
 37+#define bits r4
 38+#define off r5
 39+#define wrnk r6 /* 0x500 M2_MAX_OFFSET before "wrinkle" */
 40+#define srclim r7
 41+
 42+#define cnt r1 /* overlaps 'len' while reading an offset */
 43+
 44+/* "mov lr,pc; bxx ..." implements conditional subroutine call */
 45+#define GETBIT add bits,bits; mov lr,pc; beq get1_n2e
 46+
 47+#define getnextb(reg) GETBIT; adc reg,reg
 48+#define jnextb0 GETBIT; bcc
 49+#define jnextb1 GETBIT; bcs
 50+
 51+.section .icode.ucl_decompress, "ax", %progbits
 52+.align 2
 53+ucl_decompress: .globl ucl_nrv2e_decompress_8 @ ARM mode
 54+ .type ucl_nrv2e_decompress_8, %function
 55+/* error = (*)(char const *src, int len_src, char *dst, int *plen_dst)
 56+ Actual decompressed length is stored through plen_dst.
 57+*/
 58+ adr r12,1+.thumb_nrv2e_d8; bx r12 @ enter THUMB mode
 59+ .code 16 @ THUMB mode
 60+ .thumb_func
 61+
 62+.thumb_nrv2e_d8:
 63+ push {r2,r3,r4,r5,r6,r7,lr}
 64+ add srclim,len,src @ srclim= eof_src;
 65+ mov bits,#1; neg off,bits @ off= -1 initial condition
 66+ lsl bits,#31 @ 1<<31: refill next time
 67+ mov wrnk,#5
 68+ lsl wrnk,#8 @ 0x500 @ nrv2e M2_MAX_OFFSET
 69+ b top_n2e
 70+
 71+eof_n2e:
 72+ pop {r3,r4} @ r3= orig_dst; r4= plen_dst
 73+ sub src,srclim @ 0 if actual src length equals expected length
 74+ sub dst,r3 @ actual dst length
 75+ str dst,[r4]
 76+ pop {r4,r5,r6,r7}
 77+ pop {r1}
 78+ bx r1
 79+
 80+get1_n2e: @ In: Carry set [from adding 0x80000000 (1<<31) to itself]
 81+ ldrb bits,[src] @ zero-extend next byte
 82+ adc bits,bits @ double and insert CarryIn as low bit
 83+ add src,#1
 84+ lsl bits,#24 @ move to top byte, and set CarryOut from old bit 8
 85+ mov pc,lr @ return, stay in current (THUMB) mode
 86+
 87+lit_n2e:
 88+ ldrb tmp,[src]; add src,#1
 89+ strb tmp,[dst]; add dst,#1
 90+top_n2e:
 91+ jnextb1 lit_n2e
 92+ mov cnt,#1; b getoff_n2e
 93+
 94+off_n2e:
 95+ sub cnt,#1
 96+ getnextb(cnt)
 97+getoff_n2e:
 98+ getnextb(cnt)
 99+ jnextb0 off_n2e
 100+
 101+ sub tmp,cnt,#3 @ set Carry
 102+ mov len,#0 @ Carry unaffected
 103+ blo offprev_n2e @ cnt was 2; tests Carry only
 104+ lsl tmp,#8
 105+ ldrb off,[src]; add src,#1 @ low 7+1 bits
 106+ orr off,tmp
 107+ mvn off,off; beq eof_n2e @ off= ~off
 108+ asr off,#1; bcs lenlast_n2e
 109+ b lenmore_n2e
 110+
 111+offprev_n2e:
 112+ jnextb1 lenlast_n2e
 113+lenmore_n2e:
 114+ mov len,#1
 115+ jnextb1 lenlast_n2e
 116+len_n2e:
 117+ getnextb(len)
 118+ jnextb0 len_n2e
 119+ add len,#6-2
 120+ b gotlen_n2e
 121+
 122+lenlast_n2e:
 123+ getnextb(len) @ 0,1,2,3
 124+ add len,#2
 125+gotlen_n2e: @ 'cmn': add the inputs, set condition codes, discard the sum
 126+ cmn wrnk,off; bcs near_n2e @ within M2_MAX_OFFSET
 127+ add len,#1 @ too far away, so minimum match length is 3
 128+near_n2e:
 129+ ldrb tmp,[dst] @ force cacheline allocate
 130+copy_n2e:
 131+ ldrb tmp,[dst,off]
 132+ strb tmp,[dst]; add dst,#1
 133+ sub len,#1; bne copy_n2e
 134+ b top_n2e
 135+
 136+ .size ucl_decompress, .-ucl_decompress
Index: embios/branches/4g_compat/snprintf.c
@@ -0,0 +1,91 @@
 2+/***************************************************************************
 3+ * __________ __ ___.
 4+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
 5+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
 6+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
 7+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
 8+ * \/ \/ \/ \/ \/
 9+ * $Id$
 10+ *
 11+ * Copyright (C) 2002 by Gary Czvitkovicz
 12+ *
 13+ * This program is free software; you can redistribute it and/or
 14+ * modify it under the terms of the GNU General Public License
 15+ * as published by the Free Software Foundation; either version 2
 16+ * of the License, or (at your option) any later version.
 17+ *
 18+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 19+ * KIND, either express or implied.
 20+ *
 21+ ****************************************************************************/
 22+
 23+/*
 24+ * Minimal printf and snprintf formatting functions
 25+ *
 26+ * These support %c %s %d and %x
 27+ * Field width and zero-padding flag only
 28+ */
 29+
 30+#include "global.h"
 31+#include <stdio.h>
 32+#include <stdarg.h>
 33+#include <stdbool.h>
 34+#include <limits.h>
 35+#include "format.h"
 36+
 37+
 38+struct for_snprintf {
 39+ unsigned char *ptr; /* where to store it */
 40+ size_t bytes; /* amount already stored */
 41+ size_t max; /* max amount to store */
 42+};
 43+
 44+static int sprfunc(void *ptr, unsigned char letter)
 45+{
 46+ struct for_snprintf *pr = (struct for_snprintf *)ptr;
 47+ if(pr->bytes < pr->max) {
 48+ *pr->ptr = letter;
 49+ pr->ptr++;
 50+ pr->bytes++;
 51+ return true;
 52+ }
 53+ return false; /* filled buffer */
 54+}
 55+
 56+
 57+int snprintf(char *buf, size_t size, const char *fmt, ...)
 58+{
 59+ bool ok;
 60+ va_list ap;
 61+ struct for_snprintf pr;
 62+
 63+ pr.ptr = (unsigned char *)buf;
 64+ pr.bytes = 0;
 65+ pr.max = size;
 66+
 67+ va_start(ap, fmt);
 68+ ok = format(sprfunc, &pr, fmt, ap);
 69+ va_end(ap);
 70+
 71+ /* make sure it ends with a trailing zero */
 72+ pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
 73+
 74+ return pr.bytes;
 75+}
 76+
 77+int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
 78+{
 79+ bool ok;
 80+ struct for_snprintf pr;
 81+
 82+ pr.ptr = (unsigned char *)buf;
 83+ pr.bytes = 0;
 84+ pr.max = size;
 85+
 86+ ok = format(sprfunc, &pr, fmt, ap);
 87+
 88+ /* make sure it ends with a trailing zero */
 89+ pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
 90+
 91+ return pr.bytes;
 92+}
Index: embios/branches/4g_compat/init.c
@@ -0,0 +1,36 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+#include "lcdconsole.h"
 27+
 28+void init() INITCODE_ATTR;
 29+void init()
 30+{
 31+ lcdconsole_init();
 32+ lcdconsole_puts("emBIOS v" VERSION "\n\nStorage init...", 0, -1);
 33+ lcdconsole_update();
 34+ if (fat32_init()) lcdconsole_puts(" failed!\n", 0, -1);
 35+ else lcdconsole_puts(" done\n", 0, -1);
 36+ lcdconsole_update();
 37+}
\ No newline at end of file
Index: embios/branches/4g_compat/global.h
@@ -0,0 +1,45 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __GLOBAL_H__
 26+#define __GLOBAL_H__
 27+
 28+#ifndef ASM_FILE
 29+#include <stdint.h>
 30+#include <stddef.h>
 31+#endif
 32+
 33+#define VERSION "0.0.1pre"
 34+
 35+#define ICODE_ATTR __attribute__ ((section(".icode")))
 36+#define ICONST_ATTR __attribute__ ((section(".irodata")))
 37+#define IDATA_ATTR __attribute__ ((section(".idata")))
 38+#define IBSS_ATTR __attribute__ ((section(".ibss")))
 39+#define INITCODE_ATTR __attribute__ ((section(".initcode")))
 40+#define INITCONST_ATTR __attribute__ ((section(".initrodata")))
 41+#define INITDATA_ATTR __attribute__ ((section(".initdata")))
 42+#define INITBSS_ATTR __attribute__ ((section(".initbss")))
 43+
 44+#include "target.h"
 45+
 46+#endif
Index: embios/branches/4g_compat/strlen.c
@@ -0,0 +1,36 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+#include <string.h>
 27+#include <limits.h>
 28+
 29+size_t strlen(_CONST char *str)
 30+{
 31+ _CONST char *start = str;
 32+
 33+ while (*str)
 34+ str++;
 35+
 36+ return str - start;
 37+}
Index: embios/branches/4g_compat/console.h
@@ -0,0 +1,39 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __CONSOLE_H__
 26+#define __CONSOLE_H__
 27+
 28+
 29+#include "global.h"
 30+#include <stdarg.h>
 31+
 32+
 33+void cputc(unsigned int consoles, char string) ICODE_ATTR;
 34+void cputs(unsigned int consoles, const char* string) ICODE_ATTR;
 35+int cprintf(unsigned int consoles, const char* fmt, ...) ICODE_ATTR;
 36+int cvprintf(unsigned int consoles, const char* fmt, va_list ap) ICODE_ATTR;
 37+void cflush(unsigned int consoles) ICODE_ATTR;
 38+
 39+
 40+#endif
Index: embios/branches/4g_compat/snprintf.h
@@ -0,0 +1,39 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __PANIC_H__
 26+#define __PANIC_H__
 27+
 28+
 29+#define __need___va_list
 30+#include <stdarg.h>
 31+#include "global.h"
 32+
 33+
 34+int vsnprintf (char *buf, size_t size, const char *fmt, __VALIST ap);
 35+
 36+int snprintf (char *buf, size_t size, const char *fmt, ...)
 37+ ATTRIBUTE_PRINTF(3, 4);
 38+
 39+
 40+#endif
Index: embios/branches/4g_compat/util.c
@@ -0,0 +1,52 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+#include "util.h"
 27+
 28+
 29+void* memcpy(void* destination, const void* source, size_t num)
 30+{
 31+ unsigned char* dest = (unsigned char*)destination;
 32+ unsigned char* src = (unsigned char*)source;
 33+ while (num--) *dest++ = *src++;
 34+ return destination;
 35+}
 36+
 37+void* memset(void* ptr, int value, size_t num)
 38+{
 39+ unsigned char* dest = (unsigned char*)ptr;
 40+ while (num--) *dest++ = (unsigned char)value;
 41+ return ptr;
 42+}
 43+
 44+int memcmp(const void* ptr1, const void* ptr2, size_t num)
 45+{
 46+ unsigned char* src1 = (unsigned char*)ptr1;
 47+ unsigned char* src2 = (unsigned char*)ptr2;
 48+ int diff;
 49+ while (num--)
 50+ if (diff = *src1++ - *src2++)
 51+ return diff;
 52+ return 0;
 53+}
Index: embios/branches/4g_compat/fat32.c
@@ -0,0 +1,349 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+#include "storage.h"
 27+#include "fat32.h"
 28+#include "util.h"
 29+
 30+
 31+uint32_t fat32_ok;
 32+uint32_t fat32_startsector;
 33+uint32_t fat32_secperclus;
 34+uint32_t fat32_database;
 35+uint32_t fat32_fatbase;
 36+uint32_t fat32_fatsize;
 37+uint32_t fat32_fatcount;
 38+uint32_t fat32_sectorcount;
 39+uint32_t fat32_clustercount;
 40+uint32_t fat32_rootdirclus;
 41+uint32_t fat32_buf1[0x200] __attribute__((aligned(16)));
 42+uint32_t fat32_buf2[0x200] __attribute__((aligned(16)));
 43+
 44+
 45+uint32_t fat32_get_root()
 46+{
 47+ return fat32_rootdirclus;
 48+}
 49+
 50+uint32_t fat32_get_clusterchain(uint32_t clusterchain, uint32_t maxsize, void* buffer)
 51+{
 52+ uint32_t i;
 53+ for (i = 0; i < (maxsize >> 11); )
 54+ {
 55+ uint32_t sector = (clusterchain - 2) * fat32_secperclus + fat32_database;
 56+ uint32_t count = fat32_secperclus;
 57+ if (count + i > (maxsize >> 11)) count = (maxsize >> 11) - i;
 58+ uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
 59+ if (storage_read(fatsector, 1, &((uint32_t*)buffer)[i << 9])) return 1;
 60+ clusterchain = ((uint32_t*)buffer)[(i << 9) + (clusterchain & 0x1FF)];
 61+ if (storage_read(sector, count, &((uint32_t*)buffer)[i << 9])) return 1;
 62+ i += count;
 63+ if (clusterchain >= 0x0ffffff0) return 0;
 64+ }
 65+ return clusterchain;
 66+}
 67+
 68+uint32_t fat32_get_direntry(uint32_t clusterchain, const char* filename, uint32_t* filesize)
 69+{
 70+ uint32_t i, j;
 71+ while (clusterchain > 1 && clusterchain < 0x0ffffff0)
 72+ {
 73+ uint32_t sector = (clusterchain - 2) * fat32_secperclus + fat32_database;
 74+ for (j = 0; j < fat32_secperclus; j++)
 75+ {
 76+ if (storage_read(sector + j, 1, fat32_buf1)) return 1;
 77+ for (i = 0; i < 0x200; i += 8)
 78+ if (((uint8_t*)fat32_buf1)[i << 2] == 0) return 0;
 79+ else if (((uint8_t*)fat32_buf1)[i << 2] == 0xe5) continue;
 80+ else if (memcmp(&fat32_buf1[i], filename, 11) == 0)
 81+ {
 82+ *filesize = fat32_buf1[i + 7];
 83+ return (((uint16_t*)fat32_buf1)[(i << 1) + 0xA] << 16)
 84+ | ((uint16_t*)fat32_buf1)[(i << 1) + 0xD];
 85+ }
 86+ }
 87+ uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
 88+ if (storage_read(fatsector, 1, fat32_buf1)) return 1;
 89+ clusterchain = fat32_buf1[(i << 9) + (clusterchain & 0x1FF)];
 90+ }
 91+ return 0;
 92+}
 93+
 94+uint32_t fat32_delete_clusterchain(uint32_t clusterchain)
 95+{
 96+ while (1)
 97+ {
 98+ uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
 99+ if (storage_read(fatsector, 1, fat32_buf1)) return 1;
 100+ clusterchain = fat32_buf1[clusterchain & 0x1FF];
 101+ fat32_buf1[(clusterchain & 0x1FF)] = 0;
 102+ if (storage_write(fatsector, 1, fat32_buf1)) return 1;
 103+ if (clusterchain >= 0x0ffffff0) return 0;
 104+ }
 105+}
 106+
 107+uint32_t fat32_delete_direntry(uint32_t clusterchain, const char* filename)
 108+{
 109+ uint32_t i, j;
 110+ while (clusterchain > 1 && clusterchain < 0x0ffffff0)
 111+ {
 112+ uint32_t sector = (clusterchain - 2) * fat32_secperclus + fat32_database;
 113+ for (j = 0; j < fat32_secperclus; j++)
 114+ {
 115+ if (storage_read(sector + j, 1, fat32_buf1)) return 1;
 116+ for (i = 0; i < 0x200; i += 8)
 117+ if (((uint8_t*)fat32_buf1)[i << 2] == 0) return 0;
 118+ else if (((uint8_t*)fat32_buf1)[i << 2] == 0xe5) continue;
 119+ else if (memcmp(&fat32_buf1[i], filename, 11) == 0)
 120+ {
 121+ ((uint8_t*)fat32_buf1)[i << 2] = 0xe5;
 122+ if (storage_write(sector + j, 1, fat32_buf1)) return 1;
 123+ return 0;
 124+ }
 125+ }
 126+ uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
 127+ if (storage_read(fatsector, 1, fat32_buf1)) return 1;
 128+ clusterchain = fat32_buf1[(i << 9) + (clusterchain & 0x1FF)];
 129+ }
 130+ return 0;
 131+}
 132+
 133+uint32_t fat32_store_stream(void* buffer, uint32_t size)
 134+{
 135+ uint32_t i;
 136+ uint32_t clusterchain = 0;
 137+ uint32_t scanidx = 2;
 138+ uint32_t scansect = 0xffffffff;
 139+ uint32_t lastidx;
 140+ uint32_t lastsect = 0xffffffff;
 141+ uint32_t dirty = 0;
 142+ while (size)
 143+ {
 144+ while (scanidx < fat32_clustercount + 2)
 145+ {
 146+ if ((scanidx >> 9) != scansect)
 147+ {
 148+ scansect = scanidx >> 9;
 149+ if (storage_read(fat32_fatbase + scansect, 1, fat32_buf1)) return 0;
 150+ }
 151+ if (!fat32_buf1[scanidx & 0x1ff]) break;
 152+ scanidx++;
 153+ }
 154+ if (scanidx >= fat32_clustercount + 2) return 0;
 155+ if (!clusterchain) clusterchain = scanidx;
 156+ else
 157+ {
 158+ fat32_buf2[lastidx & 0x1ff] = scanidx;
 159+ dirty = 1;
 160+ }
 161+ lastidx = scanidx;
 162+ if ((lastidx >> 9) != lastsect)
 163+ {
 164+ if (dirty)
 165+ if (storage_write(fat32_fatbase + lastsect, 1, fat32_buf2)) return 0;
 166+ dirty = 0;
 167+ lastsect = lastidx >> 9;
 168+ memcpy(fat32_buf2, fat32_buf1, 0x800);
 169+ }
 170+ uint32_t sector = (scanidx - 2) * fat32_secperclus + fat32_database;
 171+ uint32_t count = (size + 0x7ff) >> 11;
 172+ if (count > fat32_secperclus) count = fat32_secperclus;
 173+ if (storage_write(sector, count, &((uint32_t*)buffer)[i << 9])) return 0;
 174+ if ((count << 11) >= size)
 175+ {
 176+ fat32_buf2[lastidx & 0x1ff] = 0x0fffffff;
 177+ if (storage_write(fat32_fatbase + lastsect, 1, fat32_buf2)) return 0;
 178+ break;
 179+ }
 180+ size -= count << 11;
 181+ buffer = (void*)((uint32_t)buffer + (count << 11));
 182+ scanidx++;
 183+ }
 184+ return clusterchain;
 185+}
 186+
 187+void fat32_set_direntry(uint32_t* ptr, const char* filename, uint32_t filechain,
 188+ uint32_t filesize, uint32_t flags)
 189+{
 190+ memcpy(ptr, filename, 11);
 191+ ((uint16_t*)ptr)[0xa] = filechain >> 16;
 192+ ((uint8_t*)ptr)[0xb] = flags;
 193+ ((uint16_t*)ptr)[0xa] = filechain >> 16;
 194+ ((uint16_t*)ptr)[0xd] = filechain & 0xffff;
 195+ ptr[7] = filesize;
 196+}
 197+
 198+uint32_t fat32_store_direntry(uint32_t dirchain, const char* filename,
 199+ uint32_t filechain, uint32_t filesize, uint32_t flags)
 200+{
 201+ uint32_t i, j;
 202+ uint32_t lastidx;
 203+ while (dirchain > 1 && dirchain < 0x0ffffff0)
 204+ {
 205+ uint32_t sector = (dirchain - 2) * fat32_secperclus + fat32_database;
 206+ for (j = 0; j < fat32_secperclus; j++)
 207+ {
 208+ if (storage_read(sector + j, 1, fat32_buf1)) return 1;
 209+ for (i = 0; i < 0x200; i += 8)
 210+ if (((uint8_t*)fat32_buf1)[i << 2] == 0
 211+ || ((uint8_t*)fat32_buf1)[i << 2] == 0xe5)
 212+ {
 213+ fat32_set_direntry(&fat32_buf1[i], filename, filechain, filesize, flags);
 214+ if (storage_write(sector + j, 1, fat32_buf1)) return 1;
 215+ return 0;
 216+ }
 217+ }
 218+ uint32_t fatsector = fat32_fatbase + (dirchain >> 9);
 219+ if (storage_read(fatsector, 1, fat32_buf1)) return 1;
 220+ lastidx = dirchain;
 221+ dirchain = fat32_buf1[(i << 9) + (dirchain & 0x1FF)];
 222+ }
 223+ uint32_t scanidx = 2;
 224+ uint32_t scansect = 0xffffffff;
 225+ while (scanidx < fat32_clustercount + 2)
 226+ {
 227+ if ((scanidx >> 9) != scansect)
 228+ {
 229+ scansect = scanidx >> 9;
 230+ if (storage_read(fat32_fatbase + scansect, 1, fat32_buf1)) return 1;
 231+ }
 232+ if (!fat32_buf1[scanidx & 0x1ff]) break;
 233+ scanidx++;
 234+ }
 235+ if (scanidx >= fat32_clustercount + 2) return 1;
 236+ fat32_buf1[scanidx & 0x1ff] = 0x0fffffff;
 237+ if (storage_write(fat32_fatbase + scansect, 1, fat32_buf1)) return 1;
 238+ if (storage_read(fat32_fatbase + (lastidx >> 9), 1, fat32_buf1)) return 1;
 239+ fat32_buf1[lastidx & 0x1ff] = scanidx;
 240+ if (storage_write(fat32_fatbase + scansect, 1, fat32_buf1)) return 1;
 241+ uint32_t sector = (scanidx - 2) * fat32_secperclus + fat32_database;
 242+ for (i = 0; i < fat32_secperclus; i++)
 243+ {
 244+ memset(fat32_buf1, 0, 0x800);
 245+ if (!i) fat32_set_direntry(fat32_buf1, filename, filechain, filesize, flags);
 246+ if (storage_write(sector + i, 1, fat32_buf1)) return 1;
 247+ }
 248+ return 0;
 249+}
 250+
 251+uint32_t fat32_create_dir(uint32_t parent, const char* dirname)
 252+{
 253+ uint32_t i;
 254+ uint32_t scanidx = 2;
 255+ uint32_t scansect = 0xffffffff;
 256+ while (scanidx < fat32_clustercount + 2)
 257+ {
 258+ if ((scanidx >> 9) != scansect)
 259+ {
 260+ scansect = scanidx >> 9;
 261+ if (storage_read(fat32_fatbase + scansect, 1, fat32_buf1)) return 0;
 262+ }
 263+ if (!fat32_buf1[scanidx & 0x1ff]) break;
 264+ scanidx++;
 265+ }
 266+ if (scanidx >= fat32_clustercount + 2) return 0;
 267+ fat32_buf1[scanidx & 0x1ff] = 0x0fffffff;
 268+ if (storage_write(fat32_fatbase + scansect, 1, fat32_buf1)) return 0;
 269+ fat32_store_direntry(parent, dirname, scanidx, 0, 0x10);
 270+ uint32_t sector = (scanidx - 2) * fat32_secperclus + fat32_database;
 271+ for (i = 0; i < fat32_secperclus; i++)
 272+ {
 273+ memset(fat32_buf1, 0, 0x800);
 274+ if (!i)
 275+ {
 276+ fat32_set_direntry(fat32_buf1, ". ", scanidx, 0, 0x10);
 277+ if (parent == fat32_rootdirclus) parent = 0;
 278+ fat32_set_direntry(&fat32_buf1[8], ".. ", parent, 0, 0x10);
 279+ }
 280+ if (storage_write(sector + i, 1, fat32_buf1)) return 0;
 281+ }
 282+ return scanidx;
 283+}
 284+
 285+uint32_t fat32_read_file(const char* filename, uint32_t maxsize, void* buffer, uint32_t* filesize)
 286+{
 287+}
 288+
 289+uint32_t fat32_get_partition_start()
 290+{
 291+ return fat32_startsector;
 292+}
 293+
 294+uint32_t fat32_init()
 295+{
 296+ uint32_t i;
 297+ fat32_ok = 0;
 298+ fat32_startsector = 0xFFFFFFFF;
 299+ if (storage_init()) return 1;
 300+
 301+ if (storage_read(0, 1, fat32_buf1)) return 1;
 302+
 303+ if (*((uint16_t*)((uint32_t)fat32_buf1 + 0x1FE)) != 0xAA55)
 304+ {
 305+ return 1;
 306+ }
 307+
 308+ for (i = 0x1C2; i < 0x200; i += 0x10)
 309+ if (((uint8_t*)fat32_buf1)[i] == 0xB)
 310+ {
 311+ fat32_startsector = *((uint16_t*)((uint32_t)fat32_buf1 + i + 4))
 312+ | (*((uint16_t*)((uint32_t)fat32_buf1 + i + 6)) << 16);
 313+ break;
 314+ }
 315+
 316+ if (fat32_startsector == 0xFFFFFFFF
 317+ && *((uint16_t*)((uint32_t)fat32_buf1 + 0x52)) == 0x4146
 318+ && *((uint8_t*)((uint32_t)fat32_buf1 + 0x54)) == 0x54)
 319+ fat32_startsector = 0;
 320+
 321+ if (fat32_startsector == 0xFFFFFFFF) return 1;
 322+
 323+ if (storage_read(fat32_startsector, 1, fat32_buf1)) return 1;
 324+
 325+ if (*((uint16_t*)((uint32_t)fat32_buf1 + 0x1FE)) != 0xAA55) return 1;
 326+
 327+ if (((uint8_t*)fat32_buf1)[0xB] != 0 || ((uint8_t*)fat32_buf1)[0xC] != 8) return 1;
 328+
 329+ fat32_secperclus = ((uint8_t*)fat32_buf1)[0xD];
 330+ uint32_t reserved = ((uint16_t*)fat32_buf1)[0x7];
 331+ fat32_fatcount = ((uint8_t*)fat32_buf1)[0x10];
 332+
 333+ if (((uint8_t*)fat32_buf1)[0x11] != 0) return 1;
 334+
 335+ fat32_sectorcount = fat32_buf1[8];
 336+ fat32_fatsize = fat32_buf1[9];
 337+
 338+ if (((uint16_t*)fat32_buf1)[0x15] != 0) return 1;
 339+
 340+ fat32_rootdirclus = fat32_buf1[0xB];
 341+
 342+ fat32_clustercount = (fat32_sectorcount - reserved
 343+ - fat32_fatcount * fat32_fatsize) / fat32_secperclus;
 344+
 345+ fat32_fatbase = fat32_startsector + reserved;
 346+ fat32_database = fat32_fatbase + fat32_fatcount * fat32_fatsize;
 347+
 348+ fat32_ok = 1;
 349+ return 0;
 350+}
Index: embios/branches/4g_compat/util.h
@@ -0,0 +1,36 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __UTIL_H__
 26+#define __UTIL_H__
 27+
 28+
 29+#include "global.h"
 30+
 31+
 32+void* memcpy(void* destination, const void* source, size_t num) ICODE_ATTR;
 33+void* memset(void* ptr, int value, size_t num) ICODE_ATTR;
 34+int memcmp(const void* ptr1, const void* ptr2, size_t num) ICODE_ATTR;
 35+
 36+
 37+#endif
Index: embios/branches/4g_compat/main.c
@@ -0,0 +1,29 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+
 27+void main()
 28+{
 29+ panic("main() doesn't know what to do!");
 30+}
\ No newline at end of file
Index: embios/branches/4g_compat/fat32.h
@@ -0,0 +1,44 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __FAT32_H__
 26+#define __FAT32_H__
 27+
 28+#include "global.h"
 29+
 30+uint32_t fat32_get_root();
 31+uint32_t fat32_get_clusterchain(uint32_t clusterchain, uint32_t maxsize, void* buffer);
 32+uint32_t fat32_get_direntry(uint32_t clusterchain, const char* filename, uint32_t* filesize);
 33+uint32_t fat32_delete_clusterchain(uint32_t clusterchain);
 34+uint32_t fat32_delete_direntry(uint32_t clusterchain, const char* filename);
 35+uint32_t fat32_store_stream(void* buffer, uint32_t size);
 36+uint32_t fat32_store_direntry(uint32_t dirchain, const char* filename,
 37+ uint32_t filechain, uint32_t filesize, uint32_t flags);
 38+uint32_t fat32_create_dir(uint32_t parent, const char* dirname);
 39+uint32_t fat32_read_file(const char* filename, uint32_t maxsize, void* buffer, uint32_t* filesize);
 40+uint32_t fat32_resize_patchdirs(uint32_t clusterchain, uint32_t clustoffset);
 41+uint32_t fat32_resize_fulldisk();
 42+uint32_t fat32_get_partition_start();
 43+uint32_t fat32_init();
 44+
 45+#endif
Index: embios/branches/4g_compat/format.c
@@ -0,0 +1,192 @@
 2+/***************************************************************************
 3+ * __________ __ ___.
 4+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
 5+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
 6+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
 7+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
 8+ * \/ \/ \/ \/ \/
 9+ * $Id$
 10+ *
 11+ * Copyright (C) 2002 by Gary Czvitkovicz
 12+ *
 13+ * This program is free software; you can redistribute it and/or
 14+ * modify it under the terms of the GNU General Public License
 15+ * as published by the Free Software Foundation; either version 2
 16+ * of the License, or (at your option) any later version.
 17+ *
 18+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 19+ * KIND, either express or implied.
 20+ *
 21+ ****************************************************************************/
 22+
 23+
 24+#include <stdarg.h>
 25+#include <stdbool.h>
 26+#include <limits.h>
 27+#include <string.h>
 28+
 29+static const char hexdigit[] = "0123456789ABCDEF";
 30+
 31+int format(
 32+ /* call 'push()' for each output letter */
 33+ int (*push)(void *userp, unsigned char data),
 34+ void *userp,
 35+ const char *fmt,
 36+ va_list ap)
 37+{
 38+ char *str;
 39+ char tmpbuf[12], pad;
 40+ int ch, width, val, sign, precision;
 41+ long lval, lsign;
 42+ unsigned int uval;
 43+ unsigned long ulval;
 44+ bool ok = true;
 45+
 46+ tmpbuf[sizeof tmpbuf - 1] = '\0';
 47+
 48+ while ((ch = *fmt++) != '\0' && ok)
 49+ {
 50+ if (ch == '%')
 51+ {
 52+ ch = *fmt++;
 53+ pad = ' ';
 54+ if (ch == '0')
 55+ pad = '0';
 56+
 57+ width = 0;
 58+ while (ch >= '0' && ch <= '9')
 59+ {
 60+ width = 10*width + ch - '0';
 61+ ch = *fmt++;
 62+ }
 63+
 64+ precision = 0;
 65+ if(ch == '.')
 66+ {
 67+ ch = *fmt++;
 68+ while (ch >= '0' && ch <= '9')
 69+ {
 70+ precision = 10*precision + ch - '0';
 71+ ch = *fmt++;
 72+ }
 73+ } else {
 74+ precision = INT_MAX;
 75+ }
 76+
 77+ str = tmpbuf + sizeof tmpbuf - 1;
 78+ switch (ch)
 79+ {
 80+ case 'c':
 81+ *--str = va_arg (ap, int);
 82+ break;
 83+
 84+ case 's':
 85+ str = va_arg (ap, char*);
 86+ break;
 87+
 88+ case 'd':
 89+ val = sign = va_arg (ap, int);
 90+ if (val < 0)
 91+ val = -val;
 92+ do
 93+ {
 94+ *--str = (val % 10) + '0';
 95+ val /= 10;
 96+ }
 97+ while (val > 0);
 98+ if (sign < 0)
 99+ *--str = '-';
 100+ break;
 101+
 102+ case 'u':
 103+ uval = va_arg(ap, unsigned int);
 104+ do
 105+ {
 106+ *--str = (uval % 10) + '0';
 107+ uval /= 10;
 108+ }
 109+ while (uval > 0);
 110+ break;
 111+
 112+ case 'x':
 113+ case 'X':
 114+ pad='0';
 115+ uval = va_arg (ap, int);
 116+ do
 117+ {
 118+ *--str = hexdigit[uval & 0xf];
 119+ uval >>= 4;
 120+ }
 121+ while (uval);
 122+ break;
 123+
 124+ case 'l':
 125+ case 'z': /* assume sizeof(size_t) == sizeof(long) */
 126+ ch = *fmt++;
 127+ switch(ch) {
 128+ case 'x':
 129+ case 'X':
 130+ pad='0';
 131+ ulval = va_arg (ap, long);
 132+ do
 133+ {
 134+ *--str = hexdigit[ulval & 0xf];
 135+ ulval >>= 4;
 136+ }
 137+ while (ulval);
 138+ break;
 139+ case 'd':
 140+ lval = lsign = va_arg (ap, long);
 141+ if (lval < 0)
 142+ lval = -lval;
 143+ do
 144+ {
 145+ *--str = (lval % 10) + '0';
 146+ lval /= 10;
 147+ }
 148+ while (lval > 0);
 149+ if (lsign < 0)
 150+ *--str = '-';
 151+ break;
 152+
 153+ case 'u':
 154+ ulval = va_arg(ap, unsigned long);
 155+ do
 156+ {
 157+ *--str = (ulval % 10) + '0';
 158+ ulval /= 10;
 159+ }
 160+ while (ulval > 0);
 161+ break;
 162+
 163+ default:
 164+ *--str = 'l';
 165+ *--str = ch;
 166+ }
 167+
 168+ break;
 169+
 170+ default:
 171+ *--str = ch;
 172+ break;
 173+ }
 174+
 175+ if (width > 0)
 176+ {
 177+ width -= strlen (str);
 178+ while (width-- > 0 && ok)
 179+ ok=push(userp, pad);
 180+ }
 181+ while (*str != '\0' && ok && precision--)
 182+ ok=push(userp, *str++);
 183+ }
 184+ else
 185+ ok=push(userp, ch);
 186+ }
 187+ return ok; /* true means good */
 188+}
 189+
 190+int vuprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap)
 191+{
 192+ return format(push, userp, fmt, ap);
 193+}
Index: embios/branches/4g_compat/ucl.h
@@ -0,0 +1,34 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __UCL_H__
 26+#define __UCL_H__
 27+
 28+
 29+#include "global.h"
 30+
 31+
 32+uint32_t ucl_decompress(const void* src, uint32_t len_src, void* dst, uint32_t* plen_dst);
 33+
 34+
 35+#endif
Index: embios/branches/4g_compat/lcdconsole.h
@@ -0,0 +1,45 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#ifndef __LCDCONSOLE_H__
 26+#define __LCDCONSOLE_H__
 27+
 28+
 29+#include "global.h"
 30+#include "drawing.h"
 31+#include "lcd.h"
 32+
 33+
 34+#define LCDCONSOLE_COLS (LCD_WIDTH / FONT_WIDTH)
 35+#define LCDCONSOLE_ROWS (LCD_HEIGHT / FONT_HEIGHT)
 36+#define LCDCONSOLE_OFFSETX ((LCD_WIDTH - LCDCONSOLE_COLS * FONT_WIDTH) / 2)
 37+#define LCDCONSOLE_OFFSETY ((LCD_HEIGHT - LCDCONSOLE_ROWS * FONT_HEIGHT) / 2)
 38+
 39+
 40+void lcdconsole_init();
 41+void lcdconsole_putc(char string, int fgcolor, int bgcolor) ICODE_ATTR;
 42+void lcdconsole_puts(const char* string, int fgcolor, int bgcolor) ICODE_ATTR;
 43+void lcdconsole_update() ICODE_ATTR;
 44+
 45+
 46+#endif
Index: embios/branches/4g_compat/panic.c
@@ -0,0 +1,55 @@
 2+//
 3+//
 4+// Copyright 2010 TheSeven
 5+//
 6+//
 7+// This file is part of emBIOS.
 8+//
 9+// emBIOS is free software: you can redistribute it and/or
 10+// modify it under the terms of the GNU General Public License as
 11+// published by the Free Software Foundation, either version 2 of the
 12+// License, or (at your option) any later version.
 13+//
 14+// emBIOS is distributed in the hope that it will be useful,
 15+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 16+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 17+// See the GNU General Public License for more details.
 18+//
 19+// You should have received a copy of the GNU General Public License along
 20+// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 21+//
 22+//
 23+
 24+
 25+#include "global.h"
 26+#include "console.h"
 27+
 28+
 29+void handle_panic()
 30+{
 31+ while(1);
 32+}
 33+
 34+void panic(const char* string)
 35+{
 36+ cputs(1, "\n*PANIC*\n");
 37+ cputs(1, string);
 38+ cputc(1, '\n');
 39+ handle_panic();
 40+}
 41+
 42+void panicf(const char* string, ...)
 43+{
 44+ va_list ap;
 45+ cputs(1, "\n*PANIC*\n");
 46+ va_start(ap, string);
 47+ cvprintf(1, string, ap);
 48+ va_end(ap);
 49+ cputc(1, '\n');
 50+ handle_panic();
 51+}
 52+
 53+void __div0()
 54+{
 55+ panic("Division by zero!");
 56+}
Index: embios/branches/4g_compat/format.h
@@ -0,0 +1,37 @@
 2+/***************************************************************************
 3+ * __________ __ ___.
 4+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
 5+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
 6+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
 7+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
 8+ * \/ \/ \/ \/ \/
 9+ * $Id$
 10+ *
 11+ * Copyright (C) 2002 by Felix Arends
 12+ *
 13+ * This program is free software; you can redistribute it and/or
 14+ * modify it under the terms of the GNU General Public License
 15+ * as published by the Free Software Foundation; either version 2
 16+ * of the License, or (at your option) any later version.
 17+ *
 18+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 19+ * KIND, either express or implied.
 20+ *
 21+ ****************************************************************************/
 22+
 23+#ifndef __FORMAT_H__
 24+#define __FORMAT_H__
 25+
 26+int format(
 27+ /* call 'push()' for each output letter */
 28+ int (*push)(void *userp, unsigned char data),
 29+ void *userp,
 30+ const char *fmt,
 31+ va_list ap);
 32+
 33+/* callback function is called for every output character (byte) with userp and
 34+ * should return 0 when ch is a char other than '\0' that should stop printing */
 35+int vuprintf(int (*push)(void *userp, unsigned char data),
 36+ void *userp, const char *fmt, va_list ap);
 37+
 38+#endif /* __FORMAT_H__ */
Index: embios/branches/4g_compat
Property changes on: embios/branches/4g_compat
___________________________________________________________________
Added: svn:ignore
## -0,0 +1 ##
 39+build

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r13I said I added gnu99 but I added c99 instead. Now it is really gnu99farthen05:28, 30 July 2010