summaryrefslogtreecommitdiffstats
path: root/sys/boot/arm/at91
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2006-04-19 17:16:49 +0000
committerimp <imp@FreeBSD.org>2006-04-19 17:16:49 +0000
commitf65e9cd48e102c804c39d5fc6e1ef308cead6c92 (patch)
treea98ee56083fbc0be6ef7ccbffa5fd23a06ac797c /sys/boot/arm/at91
parentb8c014aae747b676e781aecf74fb3c52bf0b9fa6 (diff)
downloadFreeBSD-src-f65e9cd48e102c804c39d5fc6e1ef308cead6c92.zip
FreeBSD-src-f65e9cd48e102c804c39d5fc6e1ef308cead6c92.tar.gz
MFp4 (checkpoint of work in progress):
o Use a directory layout that is more akin to the i386 boot layout. o Create a libat91 for library routines that are used by one or more of the boot loaders. o Create bootiic for booting from an iic part. o Create bootspi for booting from an spi part. o Optimize the size of many of these routines (especially emac.c). Except for the emac.c optimizations, all these have been tested. o eliminate the inc directory, libat91 superceeds it. o Move linker.cfg up a layer to allow it to be shared.
Diffstat (limited to 'sys/boot/arm/at91')
-rw-r--r--sys/boot/arm/at91/Makefile5
-rw-r--r--sys/boot/arm/at91/Makefile.inc23
-rw-r--r--sys/boot/arm/at91/boot0/Makefile19
-rw-r--r--sys/boot/arm/at91/boot0/main.c4
-rw-r--r--sys/boot/arm/at91/bootiic/Makefile10
-rw-r--r--sys/boot/arm/at91/bootiic/README35
-rw-r--r--sys/boot/arm/at91/bootiic/arm_init.s122
-rw-r--r--sys/boot/arm/at91/bootiic/main.c57
-rw-r--r--sys/boot/arm/at91/bootspi/Makefile10
-rw-r--r--sys/boot/arm/at91/bootspi/README34
-rw-r--r--sys/boot/arm/at91/bootspi/arm_init.s110
-rw-r--r--sys/boot/arm/at91/bootspi/main.c57
-rw-r--r--sys/boot/arm/at91/libat91/Makefile9
-rw-r--r--sys/boot/arm/at91/libat91/at91rm9200.h (renamed from sys/boot/arm/at91/inc/AT91RM9200.h)0
-rw-r--r--sys/boot/arm/at91/libat91/at91rm9200_lowlevel.c (renamed from sys/boot/arm/at91/boot0/at91rm9200_lowlevel.c)5
-rw-r--r--sys/boot/arm/at91/libat91/at91rm9200_lowlevel.h (renamed from sys/boot/arm/at91/boot0/at91rm9200_lowlevel.h)6
-rw-r--r--sys/boot/arm/at91/libat91/eeprom.c181
-rw-r--r--sys/boot/arm/at91/libat91/eeprom.h27
-rw-r--r--sys/boot/arm/at91/libat91/emac.c665
-rw-r--r--sys/boot/arm/at91/libat91/emac.h122
-rw-r--r--sys/boot/arm/at91/libat91/env_vars.c207
-rw-r--r--sys/boot/arm/at91/libat91/env_vars.h54
-rw-r--r--sys/boot/arm/at91/libat91/getc.c (renamed from sys/boot/arm/at91/boot0/lib.c)18
-rw-r--r--sys/boot/arm/at91/libat91/lib.h (renamed from sys/boot/arm/at91/boot0/lib.h)12
-rw-r--r--sys/boot/arm/at91/libat91/loader_prompt.c426
-rw-r--r--sys/boot/arm/at91/libat91/loader_prompt.h55
-rw-r--r--sys/boot/arm/at91/libat91/p_string.c210
-rw-r--r--sys/boot/arm/at91/libat91/p_string.h39
-rw-r--r--sys/boot/arm/at91/libat91/printf.c69
-rw-r--r--sys/boot/arm/at91/libat91/putchar.c (renamed from sys/boot/arm/at91/boot0/xmodem.h)30
-rw-r--r--sys/boot/arm/at91/libat91/tag_list.c79
-rw-r--r--sys/boot/arm/at91/libat91/tag_list.h28
-rw-r--r--sys/boot/arm/at91/libat91/xmodem.c (renamed from sys/boot/arm/at91/boot0/xmodem.c)8
-rw-r--r--sys/boot/arm/at91/linker.cfg291
34 files changed, 2979 insertions, 48 deletions
diff --git a/sys/boot/arm/at91/Makefile b/sys/boot/arm/at91/Makefile
new file mode 100644
index 0000000..9c9b84f
--- /dev/null
+++ b/sys/boot/arm/at91/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= libat91 boot0 bootiic bootspi
+
+.include <bsd.subdir.mk>
diff --git a/sys/boot/arm/at91/Makefile.inc b/sys/boot/arm/at91/Makefile.inc
new file mode 100644
index 0000000..528d145
--- /dev/null
+++ b/sys/boot/arm/at91/Makefile.inc
@@ -0,0 +1,23 @@
+# $FreeBSD$
+
+CFLAGS=-O2 -mcpu=arm9 -ffreestanding \
+ -I${.CURDIR}/../libat91 \
+ -Wall -Waggregate-return -Wcast-align \
+ -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
+ -Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \
+ -Werror
+
+CFLAGS+=-DBOOT_TSC
+#CFLAGS+=-DBOOT_KB920X
+
+LIBAT91=${.OBJDIR}/../libat91/libat91.a
+
+.if defined(P)
+${P}: ${P}.out
+ objcopy -S -O binary ${P}.out ${.TARGET}
+
+${P}.out: ${OBJS}
+ ld ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LIBAT91}
+
+CLEANFILES+= ${P} ${P}.out
+.endif
diff --git a/sys/boot/arm/at91/boot0/Makefile b/sys/boot/arm/at91/boot0/Makefile
index 595cd14..cb586a2 100644
--- a/sys/boot/arm/at91/boot0/Makefile
+++ b/sys/boot/arm/at91/boot0/Makefile
@@ -1,22 +1,11 @@
# $FreeBSD$
-PROG=boot0
-SRCS=arm_init.s at91rm9200_lowlevel.c lib.c main.c xmodem.c
+P=boot0
+FILES=${P}
+SRCS=arm_init.s main.c
NO_MAN=
LDFLAGS=-e 0 -T linker.cfg
-CFLAGS=-O2 -mcpu=arm9 -ffreestanding -I${.CURDIR}/../inc
-CFLAGS+=-DBOOT0_KB9202
-#CFLAGS+=-DBOOT0_TSC
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
-CLEANFILES=${OBJS} ${PROG} ${PROG}.out
-all: ${PROG}
+.include <bsd.prog.mk>
-${PROG}: ${PROG}.out ${OBJS}
- objcopy -S -O binary ${PROG}.out ${PROG}
-
-${PROG}.out: ${OBJS}
- ld ${LDFLAGS} -o ${PROG}.out ${OBJS}
-
-clean:
- rm -f ${CLEANFILES}
diff --git a/sys/boot/arm/at91/boot0/main.c b/sys/boot/arm/at91/boot0/main.c
index bc29b2f..00073d1 100644
--- a/sys/boot/arm/at91/boot0/main.c
+++ b/sys/boot/arm/at91/boot0/main.c
@@ -24,7 +24,7 @@
* $FreeBSD$
*/
-#include "AT91RM9200.h"
+#include "at91rm9200.h"
#include "lib.h"
#include "at91rm9200_lowlevel.h"
@@ -34,7 +34,7 @@ int
main(void)
{
char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
- fn_t *fn = (fn_t *)addr;
+ fn_t *fn = (fn_t *)(SDRAM_BASE + (1 << 20)); /* Load to base + 1MB */
while (xmodem_rx(addr) == -1)
continue;
diff --git a/sys/boot/arm/at91/bootiic/Makefile b/sys/boot/arm/at91/bootiic/Makefile
new file mode 100644
index 0000000..deb30f8
--- /dev/null
+++ b/sys/boot/arm/at91/bootiic/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+P=bootiic
+FILES=${P}
+SRCS=arm_init.s main.c
+NO_MAN=
+LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
+OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
+
+.include <bsd.prog.mk>
diff --git a/sys/boot/arm/at91/bootiic/README b/sys/boot/arm/at91/bootiic/README
new file mode 100644
index 0000000..1489d7c
--- /dev/null
+++ b/sys/boot/arm/at91/bootiic/README
@@ -0,0 +1,35 @@
+$FreeBSD$
+
+This image is intended to be programmed into boot EEPROM. The image is nearly
+0x4000 so it will not fit in KB9200's 0x2000. It is intended for KB9201 or
+later. Alternatively, the KB9200 can be upgraded with larger EEPROM.
+It performs basic functions prior to executing an image at a
+specified address. The pre-boot functions can be modified and saved back into
+EEPROM.
+The MAC address is set with 0.0.0.0.0.0 by default. This is an invalid address
+and must be changed to a valid value in order to use the ethernet interface.
+
+Memory usage:
+
+EEPROM = 0x4000
+SDRAM =
+ run stack = 0x21800000
+ variables = 0x21200000
+ ethernet = 0x21000000 (buffers and descriptors)
+
+
+Functions supported:
+
+ c - copy
+ d - display auto command table (in RAM)
+ e - execute image
+ ? - help
+ ip - set local ip
+ m - set mac
+ server_ip - set server ip
+ s - set auto command entry
+ t - create linux boot tag list
+ tftp - download image via tftp
+ w - update auto command table
+ x - download image via xmodem
+
diff --git a/sys/boot/arm/at91/bootiic/arm_init.s b/sys/boot/arm/at91/bootiic/arm_init.s
new file mode 100644
index 0000000..e405f89
--- /dev/null
+++ b/sys/boot/arm/at91/bootiic/arm_init.s
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ *
+ * Filename: arm_init.s
+ *
+ * Initialization for C-environment and basic operation. Adapted from
+ * ATMEL cstartup.s.
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ * 12JAN2005 kb_admin updated for 16KB eeprom
+ * Atmel stack prevents loading full size at once
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ ******************************************************************************/
+
+ .equ TWI_EEPROM_SIZE, 0x2000
+ .equ ARM_MODE_USER, 0x10
+ .equ ARM_MODE_FIQ, 0x11
+ .equ ARM_MODE_IRQ, 0x12
+ .equ ARM_MODE_SVC, 0x13
+ .equ ARM_MODE_ABORT, 0x17
+ .equ ARM_MODE_UNDEF, 0x1B
+ .equ ARM_MODE_SYS, 0x1F
+
+ .equ I_BIT, 0x80
+ .equ F_BIT, 0x40
+ .equ T_BIT, 0x20
+
+/*
+ * Stack definitions
+ *
+ * Start near top of internal RAM.
+ */
+
+ .equ END_INT_SRAM, 0x4000
+ .equ SVC_STACK_START, (END_INT_SRAM - 0x4)
+ .equ SVC_STACK_USE, 0x21800000
+
+start:
+
+/* vectors - must reside at address 0 */
+/* the format of this table is defined in the datasheet */
+ B InitReset @; reset
+undefvec:
+ B undefvec @; Undefined Instruction
+swivec:
+ B swivec @; Software Interrupt
+pabtvec:
+ B pabtvec @; Prefetch Abort
+dabtvec:
+ B dabtvec @; Data Abort
+rsvdvec:
+ .long (TWI_EEPROM_SIZE >> 9)
+irqvec:
+ ldr pc, [pc,#-0xF20] @; IRQ : read the AIC
+fiqvec:
+ B fiqvec @; FIQ
+
+
+InitReset:
+
+/* Set stack and init for SVC */
+ ldr r1, = SVC_STACK_START
+ mov sp, r1 @; Init stack SYS
+
+ msr cpsr_c, #(ARM_MODE_SVC | I_BIT | F_BIT)
+ mov sp, r1 @ ; Init stack SYS
+
+/* Perform system initialization */
+
+ .extern _init
+
+ bl _init
+
+ ldr r1, = SVC_STACK_USE
+ mov sp, r1 @ ; Move the stack to SDRAM
+
+/* Copy the rest of the load image from EEPROM */
+ .extern InitEEPROM
+
+ bl InitEEPROM
+
+ .extern ReadEEPROM
+
+ mov r0, #8192
+ mov r1, #8192
+ mov r2, #8192
+ bl ReadEEPROM
+
+/* Start execution at main */
+
+ .extern main
+_main:
+__main:
+ bl main
+
+/* main should not return. If it does, spin forever */
+
+infiniteLoop:
+ b infiniteLoop
+
+/* the following section is used to store boot commands in */
+/* non-volatile memory. */
+
+ .global BootCommandSection
+BootCommandSection:
+ .string "Bootloader for KB9202 Evaluation Board."
+ .string "c 0x20210000 0x10100000 0x80000 "
+ .string "m 0 0 0 0 0 0 "
+ .string "t 0x20000100 console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933"
+ .string "e 0x10000000 "
+ .string " "
diff --git a/sys/boot/arm/at91/bootiic/main.c b/sys/boot/arm/at91/bootiic/main.c
new file mode 100644
index 0000000..2642b10
--- /dev/null
+++ b/sys/boot/arm/at91/bootiic/main.c
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ *
+ * Filename: main.c
+ *
+ * Basic entry points for top-level functions
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ * 12JAN2005 kb_admin cosmetic changes
+ * 29APR2005 kb_admin modified boot delay
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ ******************************************************************************/
+
+#include "env_vars.h"
+#include "at91rm9200_lowlevel.h"
+#include "loader_prompt.h"
+#include "emac.h"
+#include "lib.h"
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * int main(void)
+ * This global function waits at least one second, but not more than two
+ * seconds, for input from the serial port. If no response is recognized,
+ * it acts according to the parameters specified by the environment. For
+ * example, the function might boot an operating system. Do not return
+ * from this function.
+ * .KB_C_FN_DEFINITION_END
+ */
+int
+main(void)
+{
+
+ EMAC_Init();
+
+ LoadBootCommands();
+
+ printf("\n\rKB9202(www.kwikbyte.com)\n\rAuto boot..\n\r");
+
+ if (getc(1) == -1)
+ ExecuteEnvironmentFunctions();
+
+ Bootloader(0);
+
+ return (1);
+}
diff --git a/sys/boot/arm/at91/bootspi/Makefile b/sys/boot/arm/at91/bootspi/Makefile
new file mode 100644
index 0000000..203d8a1
--- /dev/null
+++ b/sys/boot/arm/at91/bootspi/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+P=bootspi
+FILES=${P}
+SRCS=arm_init.s main.c
+NO_MAN=
+LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
+OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
+
+.include <bsd.prog.mk>
diff --git a/sys/boot/arm/at91/bootspi/README b/sys/boot/arm/at91/bootspi/README
new file mode 100644
index 0000000..9a4ffa8
--- /dev/null
+++ b/sys/boot/arm/at91/bootspi/README
@@ -0,0 +1,34 @@
+$FreeBSD$
+
+This image is intended to be programmed into boot EEPROM. The image is nearly
+0x4000 so it will not fit in KB9200's 0x2000. It is intended for KB9201 or
+later. Alternatively, the KB9200 can be upgraded with larger EEPROM.
+It performs basic functions prior to executing an image at a
+specified address. The pre-boot functions can be modified and saved back into
+EEPROM.
+The MAC address is set with 0.0.0.0.0.0 by default. This is an invalid address
+and must be changed to a valid value in order to use the ethernet interface.
+
+Memory usage:
+
+EEPROM = 0x4000
+SDRAM =
+ run stack = 0x21800000
+ variables = 0x21200000
+ ethernet = 0x21000000 (buffers and descriptors)
+
+
+Functions supported:
+
+ c - copy
+ d - display auto command table (in RAM)
+ e - execute image
+ ? - help
+ ip - set local ip
+ m - set mac
+ server_ip - set server ip
+ s - set auto command entry
+ t - create linux boot tag list
+ tftp - download image via tftp
+ w - update auto command table
+ x - download image via xmodem
diff --git a/sys/boot/arm/at91/bootspi/arm_init.s b/sys/boot/arm/at91/bootspi/arm_init.s
new file mode 100644
index 0000000..f9e6655
--- /dev/null
+++ b/sys/boot/arm/at91/bootspi/arm_init.s
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ *
+ * Filename: arm_init.s
+ *
+ * Initialization for C-environment and basic operation. Adapted from
+ * ATMEL cstartup.s.
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ * 12JAN2005 kb_admin updated for 16KB eeprom
+ * Atmel stack prevents loading full size at once
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ ******************************************************************************/
+
+ .equ TWI_EEPROM_SIZE, 0x2000
+ .equ ARM_MODE_USER, 0x10
+ .equ ARM_MODE_FIQ, 0x11
+ .equ ARM_MODE_IRQ, 0x12
+ .equ ARM_MODE_SVC, 0x13
+ .equ ARM_MODE_ABORT, 0x17
+ .equ ARM_MODE_UNDEF, 0x1B
+ .equ ARM_MODE_SYS, 0x1F
+
+ .equ I_BIT, 0x80
+ .equ F_BIT, 0x40
+ .equ T_BIT, 0x20
+
+/*
+ * Stack definitions
+ *
+ * Start near top of internal RAM.
+ */
+
+ .equ END_INT_SRAM, 0x4000
+ .equ SVC_STACK_START, (END_INT_SRAM - 0x4)
+ .equ SVC_STACK_USE, 0x21800000
+
+start:
+
+/* vectors - must reside at address 0 */
+/* the format of this table is defined in the datasheet */
+ B InitReset @; reset
+undefvec:
+ B undefvec @; Undefined Instruction
+swivec:
+ B swivec @; Software Interrupt
+pabtvec:
+ B pabtvec @; Prefetch Abort
+dabtvec:
+ B dabtvec @; Data Abort
+rsvdvec:
+ .long (TWI_EEPROM_SIZE >> 9)
+irqvec:
+ ldr pc, [pc,#-0xF20] @; IRQ : read the AIC
+fiqvec:
+ B fiqvec @; FIQ
+
+
+InitReset:
+
+/* Set stack and init for SVC */
+ ldr r1, = SVC_STACK_START
+ mov sp, r1 @; Init stack SYS
+
+ msr cpsr_c, #(ARM_MODE_SVC | I_BIT | F_BIT)
+ mov sp, r1 @ ; Init stack SYS
+
+/* Perform system initialization */
+
+ .extern _init
+
+ bl _init
+
+ ldr r1, = SVC_STACK_USE
+ mov sp, r1 @ ; Move the stack to SDRAM
+
+/* Start execution at main */
+
+ .extern main
+_main:
+__main:
+ bl main
+
+/* main should not return. If it does, spin forever */
+
+infiniteLoop:
+ b infiniteLoop
+
+/* the following section is used to store boot commands in */
+/* non-volatile memory. */
+
+ .global BootCommandSection
+BootCommandSection:
+ .string "Bootloader for KB9202 Evaluation Board."
+ .string "c 0x20210000 0x10100000 0x80000 "
+ .string "m 0 0 0 0 0 0 "
+ .string "t 0x20000100 console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933"
+ .string "e 0x10000000 "
+ .string " "
diff --git a/sys/boot/arm/at91/bootspi/main.c b/sys/boot/arm/at91/bootspi/main.c
new file mode 100644
index 0000000..a187eb4b
--- /dev/null
+++ b/sys/boot/arm/at91/bootspi/main.c
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ *
+ * Filename: main.c
+ *
+ * Basic entry points for top-level functions
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ * 12JAN2005 kb_admin cosmetic changes
+ * 29APR2005 kb_admin modified boot delay
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ ******************************************************************************/
+
+#include "env_vars.h"
+#include "at91rm9200_lowlevel.h"
+#include "loader_prompt.h"
+#include "emac.h"
+#include "lib.h"
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * int main(void)
+ * This global function waits at least one second, but not more than two
+ * seconds, for input from the serial port. If no response is recognized,
+ * it acts according to the parameters specified by the environment. For
+ * example, the function might boot an operating system. Do not return
+ * from this function.
+ * .KB_C_FN_DEFINITION_END
+ */
+int
+main(void)
+{
+
+ EMAC_Init();
+
+ LoadBootCommands();
+
+ printf("\r\nSPI Boot loader.\r\nAutoboot...\r\n");
+
+ if (getc(1) == -1)
+ ExecuteEnvironmentFunctions();
+
+ Bootloader(0);
+
+ return (1);
+}
diff --git a/sys/boot/arm/at91/libat91/Makefile b/sys/boot/arm/at91/libat91/Makefile
new file mode 100644
index 0000000..e85fef5
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+LIB= at91
+INTERNALLIB=
+SRCS=at91rm9200_lowlevel.c eeprom.c emac.c env_vars.c getc.c loader_prompt.c \
+ p_string.c putchar.c printf.c xmodem.c
+NO_MAN=
+
+.include <bsd.lib.mk>
diff --git a/sys/boot/arm/at91/inc/AT91RM9200.h b/sys/boot/arm/at91/libat91/at91rm9200.h
index 6fe7d07..6fe7d07 100644
--- a/sys/boot/arm/at91/inc/AT91RM9200.h
+++ b/sys/boot/arm/at91/libat91/at91rm9200.h
diff --git a/sys/boot/arm/at91/boot0/at91rm9200_lowlevel.c b/sys/boot/arm/at91/libat91/at91rm9200_lowlevel.c
index d0f10a1..cd10d25 100644
--- a/sys/boot/arm/at91/boot0/at91rm9200_lowlevel.c
+++ b/sys/boot/arm/at91/libat91/at91rm9200_lowlevel.c
@@ -27,7 +27,7 @@
* $FreeBSD$
*/
-#include "AT91RM9200.h"
+#include "at91rm9200.h"
#include "at91rm9200_lowlevel.h"
#define BAUD 115200
@@ -46,10 +46,9 @@ _init(void)
AT91PS_PDC pPDC = (AT91PS_PDC)&(pUSART->US_RPR);
register unsigned value;
- int i;
volatile sdram_size_t *p = (sdram_size_t *)SDRAM_BASE;
-#ifdef BOOT0_TSC
+#ifdef BOOT_TSC
// For the TSC board, we turn ON the one LED we have while
// early in boot.
AT91C_BASE_PIOC->PIO_PER = AT91C_PIO_PC10;
diff --git a/sys/boot/arm/at91/boot0/at91rm9200_lowlevel.h b/sys/boot/arm/at91/libat91/at91rm9200_lowlevel.h
index 8445e16..0129a91 100644
--- a/sys/boot/arm/at91/boot0/at91rm9200_lowlevel.h
+++ b/sys/boot/arm/at91/libat91/at91rm9200_lowlevel.h
@@ -31,7 +31,7 @@
#define SDRAM_BASE 0x20000000
-#ifdef BOOT0_KB9202
+#ifdef BOOT_KB9202
/* The following divisor sets PLLA frequency: e.g. 10/5 * 90 = 180MHz */
#define OSC_MAIN_FREQ_DIV 5 /* for 10MHz osc */
#define SDRAM_WIDTH AT91C_SDRC_DBW_16_BITS
@@ -39,7 +39,7 @@ typedef unsigned short sdram_size_t;
#define OSC_MAIN_MULT 90
#endif
-#ifdef BOOT0_TSC
+#ifdef BOOT_TSC
/* The following divisor sets PLLA frequency: e.g. 16/4 * 45 = 180MHz */
#define OSC_MAIN_FREQ_DIV 4 /* for 16MHz osc */
#define SDRAM_WIDTH AT91C_SDRC_DBW_16_BITS
@@ -52,6 +52,6 @@ typedef unsigned int sdram_size_t;
#define GetSeconds() (AT91C_BASE_RTC->RTC_TIMR & AT91C_RTC_SEC)
-extern void DefaultSystemInit(void);
+extern void _init(void);
#endif /* _AT91RM9200_LOWLEVEL_H_ */
diff --git a/sys/boot/arm/at91/libat91/eeprom.c b/sys/boot/arm/at91/libat91/eeprom.c
new file mode 100644
index 0000000..7c9e2ae
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/eeprom.c
@@ -0,0 +1,181 @@
+/******************************************************************************
+ *
+ * Filename: eeprom.c
+ *
+ * Instantiation of eeprom routines
+ *
+ * Revision information:
+ *
+ * 28AUG2004 kb_admin initial creation - adapted from Atmel sources
+ * 12JAN2005 kb_admin fixed clock generation, write polling, init
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+#include "at91rm9200_lowlevel.h"
+#include "at91rm9200.h"
+#include "lib.h"
+
+/******************************* GLOBALS *************************************/
+
+
+/*********************** PRIVATE FUNCTIONS/DATA ******************************/
+
+
+/* Use a macro to calculate the TWI clock generator value to save code space. */
+#define AT91C_TWSI_CLOCK 100000
+#define TWSI_EEPROM_ADDRESS 0x50
+
+#define TWI_CLK_BASE_DIV ((AT91C_MASTER_CLOCK/(4*AT91C_TWSI_CLOCK)) - 2)
+#define SET_TWI_CLOCK ((0x00010000) | (TWI_CLK_BASE_DIV) | (TWI_CLK_BASE_DIV << 8))
+
+
+/*************************** GLOBAL FUNCTIONS ********************************/
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void InitEEPROM(void)
+ * This global function initializes the EEPROM interface (TWI). Intended
+ * to be called a single time.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+InitEEPROM(void)
+{
+
+ AT91PS_TWI twiPtr = (AT91PS_TWI)AT91C_BASE_TWI;
+
+ AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
+ AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
+
+ pPio->PIO_ASR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
+ pPio->PIO_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
+
+ pPio->PIO_MDDR = ~AT91C_PA25_TWD;
+ pPio->PIO_MDER = AT91C_PA25_TWD;
+
+ pPMC->PMC_PCER = 1u << AT91C_ID_TWI;
+
+ twiPtr->TWI_IDR = 0xffffffffu;
+ twiPtr->TWI_CR = AT91C_TWI_SWRST;
+ twiPtr->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS;
+
+ twiPtr->TWI_CWGR = SET_TWI_CLOCK;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size)
+ * This global function reads data from the eeprom at ee_addr storing data
+ * to data_addr for size bytes. Assume the TWI has been initialized.
+ * This function does not utilize the page read mode to simplify the code.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size)
+{
+ const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
+ unsigned int status;
+
+ status = twiPtr->TWI_SR;
+ status = twiPtr->TWI_RHR;
+
+ // Set the TWI Master Mode Register
+ twiPtr->TWI_MMR = (TWSI_EEPROM_ADDRESS << 16) |
+ AT91C_TWI_IADRSZ_2_BYTE | AT91C_TWI_MREAD;
+
+ // Set TWI Internal Address Register
+ twiPtr->TWI_IADR = ee_addr;
+
+ // Start transfer
+ twiPtr->TWI_CR = AT91C_TWI_START;
+
+ status = twiPtr->TWI_SR;
+
+ while (size-- > 1){
+
+ // Wait RHR Holding register is full
+ while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY))
+ continue;
+
+ // Read byte
+ *(data_addr++) = twiPtr->TWI_RHR;
+ }
+
+ twiPtr->TWI_CR = AT91C_TWI_STOP;
+
+ status = twiPtr->TWI_SR;
+
+ // Wait transfer is finished
+ while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
+ continue;
+
+ // Read last byte
+ *data_addr = twiPtr->TWI_RHR;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void WriteEEPROM(unsigned ee_addr, char *data_addr, unsigned size)
+ * This global function writes data to the eeprom at ee_addr using data
+ * from data_addr for size bytes. Assume the TWI has been initialized.
+ * This function does not utilize the page write mode as the write time is
+ * much greater than the time required to access the device for byte-write
+ * functionality. This allows the function to be much simpler.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+WriteEEPROM(unsigned ee_addr, char *data_addr, unsigned size)
+{
+ const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
+ unsigned status;
+ char test_data;
+
+ while (size--) {
+ if (!(ee_addr & 0x3f))
+ putchar('.');
+
+ // Set the TWI Master Mode Register
+ twiPtr->TWI_MMR = ((TWSI_EEPROM_ADDRESS << 16) |
+ AT91C_TWI_IADRSZ_2_BYTE) & ~AT91C_TWI_MREAD;
+
+ // Set TWI Internal Address Register
+ twiPtr->TWI_IADR = ee_addr++;
+
+ status = twiPtr->TWI_SR;
+
+ twiPtr->TWI_THR = *(data_addr++);
+
+ twiPtr->TWI_CR = AT91C_TWI_START;
+
+ // Wait transfer is finished
+ while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY))
+ continue;
+
+ twiPtr->TWI_CR = AT91C_TWI_STOP;
+
+ status = twiPtr->TWI_SR;
+
+ // Wait transfer is finished
+ while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
+ continue;
+
+ // wait for write operation to complete
+ ReadEEPROM(ee_addr, &test_data, 1);
+ }
+
+ putchar('\r');
+ putchar('\n');
+}
diff --git a/sys/boot/arm/at91/libat91/eeprom.h b/sys/boot/arm/at91/libat91/eeprom.h
new file mode 100644
index 0000000..9f41ac4
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/eeprom.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ *
+ * Filename: eeprom.h
+ *
+ * Definition of eeprom routines
+ *
+ * Revision information:
+ *
+ * 28AUG2004 kb_admin initial creation - adapted from Atmel sources
+ * 12JAN2005 kb_admin add init
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ ******************************************************************************/
+
+#ifndef _EEPROM_H_
+#define _EEPROM_H_
+
+#endif /* _EEPROM_H_ */
diff --git a/sys/boot/arm/at91/libat91/emac.c b/sys/boot/arm/at91/libat91/emac.c
new file mode 100644
index 0000000..15913b4
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/emac.c
@@ -0,0 +1,665 @@
+/******************************************************************************
+ *
+ * Filename: emac.c
+ *
+ * Instantiation of routines for MAC/ethernet functions supporting tftp.
+ *
+ * Revision information:
+ *
+ * 28AUG2004 kb_admin initial creation
+ * 08JAN2005 kb_admin added tftp download
+ * also adapted from external sources
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+#include "at91rm9200.h"
+#include "emac.h"
+#include "p_string.h"
+#include "at91rm9200_lowlevel.h"
+#include "lib.h"
+
+/******************************* GLOBALS *************************************/
+
+/*********************** PRIVATE FUNCTIONS/DATA ******************************/
+
+static unsigned localMACSet, serverMACSet, MAC_init;
+static unsigned char localMACAddr[6], serverMACAddr[6];
+static unsigned localIPAddr, serverIPAddr;
+static unsigned short serverPort, localPort;
+static int ackBlock;
+
+static unsigned lastAddress, lastSize;
+static char *dlAddress;
+
+static unsigned transmitBuffer[1024 / sizeof(unsigned)];
+static unsigned tftpSendPacket[256 / sizeof(unsigned)];
+
+receive_descriptor_t *p_rxBD;
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * unsigned short IP_checksum(unsigned short *p, int len)
+ * This private function calculates the IP checksum for various headers.
+ * .KB_C_FN_DEFINITION_END
+ */
+static unsigned short
+IP_checksum(void *cp, int len)
+{
+ unsigned i, t;
+ unsigned short *p = (unsigned short *)cp;
+
+ len &= ~1;
+ for (i=0,t=0; i<len; i+=2, ++p)
+ t += SWAP16(*p);
+ t = (t & 0xffff) + (t >> 16);
+ return (~t);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void GetServerAddress(void)
+ * This private function sends an ARP request to determine the server MAC.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+GetServerAddress(void)
+{
+ arp_header_t *p_ARP;
+
+ p_ARP = (arp_header_t*)transmitBuffer;
+ p_memset((char*)p_ARP->dest_mac, 0xFF, 6);
+ p_memcpy((char*)p_ARP->src_mac, (char*)localMACAddr, 6);
+
+ p_ARP->frame_type = SWAP16(PROTOCOL_ARP);
+ p_ARP->hard_type = SWAP16(1);
+ p_ARP->prot_type = SWAP16(PROTOCOL_IP);
+ p_ARP->hard_size = 6;
+ p_ARP->prot_size = 4;
+ p_ARP->operation = SWAP16(ARP_REQUEST);
+
+ p_memcpy((char*)p_ARP->sender_mac, (char*)localMACAddr, 6);
+ p_memcpy((char*)p_ARP->sender_ip, (char*)localIPAddr, 4);
+ p_memset((char*)p_ARP->target_mac, 0, 6);
+ p_memcpy((char*)p_ARP->target_ip, (char*)serverIPAddr, 4);
+
+ // wait until transmit is available
+ while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
+
+ *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
+ *AT91C_EMAC_TAR = (unsigned)transmitBuffer;
+ *AT91C_EMAC_TCR = 0x40;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
+ * This private function initializes and send a TFTP packet.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
+{
+ transmit_header_t *macHdr = (transmit_header_t*)tftpSendPacket;
+ ip_header_t *ipHdr;
+ udp_header_t *udpHdr;
+ unsigned t_checksum;
+
+ p_memcpy((char*)macHdr->dest_mac, (char*)serverMACAddr, 6);
+ p_memcpy((char*)macHdr->src_mac, (char*)localMACAddr, 6);
+
+ macHdr->proto_mac = SWAP16(PROTOCOL_IP);
+
+ ipHdr = &macHdr->iphdr;
+
+ ipHdr->ip_v_hl = 0x45;
+ ipHdr->ip_tos = 0;
+ ipHdr->ip_len = SWAP16(28 + tftpLength);
+ ipHdr->ip_id = 0;
+ ipHdr->ip_off = SWAP16(0x4000);
+ ipHdr->ip_ttl = 64;
+ ipHdr->ip_p = PROTOCOL_UDP;
+ ipHdr->ip_sum = 0;
+
+ p_memcpy((char*)ipHdr->ip_src, (char*)localIPAddr, 4);
+ p_memcpy((char*)ipHdr->ip_dst, (char*)serverIPAddr, 4);
+
+ ipHdr->ip_sum = SWAP16(IP_checksum(ipHdr, 20));
+
+ udpHdr = (udp_header_t*)(ipHdr + 1);
+
+ udpHdr->src_port = localPort;
+ udpHdr->dst_port = serverPort;
+ udpHdr->udp_len = SWAP16(8 + tftpLength);
+ udpHdr->udp_cksum = 0;
+
+ p_memcpy((char*)udpHdr+8, tftpData, tftpLength);
+
+ t_checksum = IP_checksum((char *)ipHdr + 12, (16 + tftpLength));
+
+ t_checksum = (~t_checksum) & 0xFFFF;
+ t_checksum += 25 + tftpLength;
+
+ t_checksum = (t_checksum & 0xffff) + (t_checksum >> 16);
+ t_checksum = (~t_checksum) & 0xFFFF;
+
+ udpHdr->udp_cksum = SWAP16(t_checksum);
+
+ while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
+
+ *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
+ *AT91C_EMAC_TAR = (unsigned)tftpSendPacket;
+ *AT91C_EMAC_TCR = 42 + tftpLength;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void TFTP_RequestFile(char *filename)
+ * This private function sends a RRQ packet to the server.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+TFTP_RequestFile(char *filename)
+{
+ tftp_header_t tftpHeader;
+ char *cPtr, *ePtr, *mPtr;
+ unsigned length;
+
+ tftpHeader.opcode = SWAP16(TFTP_RRQ_OPCODE);
+
+ cPtr = (char*)&(tftpHeader.block_num);
+
+ ePtr = p_strcpy(cPtr, filename);
+ mPtr = p_strcpy(ePtr, "octet");
+
+ length = mPtr - cPtr;
+ length += 2;
+
+ Send_TFTP_Packet((char*)&tftpHeader, length);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void TFTP_ACK_Data(char *data, unsigned short block_num, unsigned short len)
+ * This private function sends an ACK packet to the server.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+TFTP_ACK_Data(char *data, unsigned short block_num, unsigned short len)
+{
+ tftp_header_t tftpHeader;
+
+ if (block_num == SWAP16(ackBlock + 1)) {
+ ++ackBlock;
+ p_memcpy(dlAddress, data, len);
+ dlAddress += len;
+ lastSize += len;
+ }
+
+ tftpHeader.opcode = SWAP16(TFTP_ACK_OPCODE);
+ tftpHeader.block_num = block_num;
+ Send_TFTP_Packet((char*)&tftpHeader, 4);
+
+ if (len < 512)
+ ackBlock = -2;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void CheckForNewPacket(ip_header_t *pHeader)
+ * This private function polls for received ethernet packets and handles
+ * any here.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+CheckForNewPacket(void)
+{
+ unsigned short *pFrameType;
+ unsigned i;
+ char *pData;
+ ip_header_t *pIpHeader;
+ arp_header_t *p_ARP;
+ int process = 0;
+
+ process = 0;
+ for (i = 0; i < MAX_RX_PACKETS; ++i) {
+ if(p_rxBD[i].address & 0x1) {
+ process = 1;
+ (*AT91C_EMAC_RSR) |= (*AT91C_EMAC_RSR);
+ break;
+ }
+ }
+
+ if (!process)
+ return ;
+
+ process = i;
+
+ pFrameType = (unsigned short *) ((p_rxBD[i].address & 0xFFFFFFFC) + 12);
+ pData = (char *)(p_rxBD[i].address & 0xFFFFFFFC);
+
+ switch (SWAP16(*pFrameType)) {
+
+ case PROTOCOL_ARP:
+ p_ARP = (arp_header_t*)pData;
+
+ i = SWAP16(p_ARP->operation);
+ if (i == ARP_REPLY) {
+
+ // check if new server info is available
+ if ((!serverMACSet) &&
+ (!(p_memcmp((char*)p_ARP->sender_ip,
+ (char*)serverIPAddr, 4)))) {
+
+ serverMACSet = 1;
+
+ p_memcpy((char*)serverMACAddr,
+ (char*)p_ARP->sender_mac, 6);
+ }
+ } else if (i == ARP_REQUEST) {
+
+ // ARP REPLY operation
+ p_ARP->operation = SWAP16(ARP_REPLY);
+
+ // Swap the src/dst MAC addr
+ p_memcpy(p_ARP->dest_mac, p_ARP->src_mac, 6);
+ p_memcpy(p_ARP->src_mac, localMACAddr, 6);
+
+ // Do IP and MAC addr at same time.
+ p_memcpy(p_ARP->target_mac, p_ARP->sender_mac, 10);
+ p_memcpy(p_ARP->sender_mac, localMACAddr, 6);
+ p_memcpy(p_ARP->sender_ip, (char *)&localIPAddr, 4);
+
+ if (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ))
+ break;
+
+ *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
+ *AT91C_EMAC_TAR = (unsigned)pData;
+ *AT91C_EMAC_TCR = 0x40;
+ }
+ break;
+
+ case PROTOCOL_IP:
+ pIpHeader = (ip_header_t*)(pData + 14);
+ switch(pIpHeader->ip_p) {
+ case PROTOCOL_UDP:
+ {
+ udp_header_t *udpHdr;
+ tftp_header_t *tftpHdr;
+
+ udpHdr = (udp_header_t*)((char*)pIpHeader+20);
+ tftpHdr = (tftp_header_t*)((char*)udpHdr + 8);
+
+ if (udpHdr->dst_port != localPort)
+ break;
+
+ if (tftpHdr->opcode != SWAP16(TFTP_DATA_OPCODE))
+ break;
+
+ if (ackBlock == -1) {
+ if (tftpHdr->block_num != SWAP16(1))
+ break;
+ serverPort = udpHdr->src_port;
+ ackBlock = 0;
+ }
+
+ if (serverPort != udpHdr->src_port)
+ break;
+
+ TFTP_ACK_Data(tftpHdr->data,
+ tftpHdr->block_num,
+ SWAP16(udpHdr->udp_len) - 12);
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ p_rxBD[process].address &= ~0x01;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * unsigned short AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
+ * This private function reads the PHY device.
+ * .KB_C_FN_DEFINITION_END
+ */
+static unsigned short
+AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
+{
+ unsigned value = 0x60020000 | (addr << 18);
+
+ pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
+ pEmac->EMAC_MAN = value;
+ while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
+ pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
+ return (pEmac->EMAC_MAN & 0x0000ffff);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void MII_GetLinkSpeed(AT91PS_EMAC pEmac)
+ * This private function determines the link speed set by the PHY.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+MII_GetLinkSpeed(AT91PS_EMAC pEmac)
+{
+ unsigned short stat2;
+ unsigned update = 0;
+
+ stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
+
+ if (!(stat2 & 0x400)) {
+ return ;
+
+ } else if (stat2 & 0x4000) {
+
+ update |= AT91C_EMAC_SPD;
+
+ if (stat2 & 0x200) {
+ update |= AT91C_EMAC_FD;
+ }
+
+ } else if (stat2 & 0x200) {
+ update |= AT91C_EMAC_FD;
+ }
+
+ pEmac->EMAC_CFG =
+ (pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) | update;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void AT91F_EmacEntry(void)
+ * This private function initializes the EMAC on the chip.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+AT91F_EmacEntry(void)
+{
+ unsigned i;
+ char *pRxPacket = (char*)RX_DATA_START;
+ AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
+
+ for (i = 0; i < MAX_RX_PACKETS; ++i) {
+ p_rxBD[i].address = (unsigned)pRxPacket;
+ p_rxBD[i].size = 0;
+ pRxPacket += RX_PACKET_SIZE;
+ }
+
+ // Set the WRAP bit at the end of the list descriptor
+ p_rxBD[MAX_RX_PACKETS-1].address |= 0x02;
+
+ pEmac->EMAC_CTL = 0;
+
+ if(!(pEmac->EMAC_SR & AT91C_EMAC_LINK))
+ MII_GetLinkSpeed(pEmac);
+
+ // the sequence write EMAC_SA1L and write EMAC_SA1H must be respected
+ pEmac->EMAC_SA1L = ((unsigned)localMACAddr[2] << 24) |
+ ((unsigned)localMACAddr[3] << 16) | ((int)localMACAddr[4] << 8) |
+ localMACAddr[5];
+ pEmac->EMAC_SA1H = ((unsigned)localMACAddr[0] << 8) | localMACAddr[1];
+
+ pEmac->EMAC_RBQP = (unsigned) p_rxBD;
+ pEmac->EMAC_RSR |= (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
+ pEmac->EMAC_CFG |= AT91C_EMAC_CAF;
+ pEmac->EMAC_CFG = (pEmac->EMAC_CFG & ~(AT91C_EMAC_CLK)) |
+ AT91C_EMAC_CLK_HCLK_32;
+ pEmac->EMAC_CTL |= (AT91C_EMAC_TE | AT91C_EMAC_RE);
+
+ pEmac->EMAC_TAR = (unsigned)transmitBuffer;
+}
+
+
+/* ************************** GLOBAL FUNCTIONS ********************************/
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void SetMACAddress(unsigned low_address, unsigned high_address)
+ * This global function sets the MAC address. low_address is the first
+ * four bytes while high_address is the last 2 bytes of the 48-bit value.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+SetMACAddress(unsigned low_address, unsigned high_address)
+{
+
+ AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
+ AT91PS_PMC pPMC = AT91C_BASE_PMC;
+
+ /* enable the peripheral clock before using EMAC */
+ pPMC->PMC_PCER = ((unsigned) 1 << AT91C_ID_EMAC);
+
+ pEmac->EMAC_SA1L = low_address;
+ pEmac->EMAC_SA1H = (high_address & 0x0000ffff);
+
+ localMACAddr[0] = (low_address >> 0) & 0xFF;
+ localMACAddr[1] = (low_address >> 8) & 0xFF;
+ localMACAddr[2] = (low_address >> 16) & 0xFF;
+ localMACAddr[3] = (low_address >> 24) & 0xFF;
+ localMACAddr[4] = (high_address >> 0) & 0xFF;
+ localMACAddr[5] = (high_address >> 8) & 0xFF;
+
+ localMACSet = 1;
+
+ // low_address & 0x000000ff = first byte in address
+ // low_address & 0x0000ff00 = next
+ // low_address & 0x00ff0000 = next
+ // low_address & 0xff000000 = next
+ // high_address & 0x000000ff = next
+ // high_address & 0x0000ff00 = last byte in address
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void SetServerIPAddress(unsigned address)
+ * This global function sets the IP of the TFTP download server.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+SetServerIPAddress(unsigned address)
+{
+ // force update in case the IP has changed
+ serverMACSet = 0;
+ serverIPAddr = address;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void SetLocalIPAddress(unsigned address)
+ * This global function sets the IP of this module.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+SetLocalIPAddress(unsigned address)
+{
+ // force update in case the IP has changed
+ serverMACSet = 0;
+ localIPAddr = address;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void TFTP_Download(unsigned address, char *filename)
+ * This global function initiates and processes a tftp download request.
+ * The server IP, local IP, local MAC must be set before this function is
+ * executed.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+TFTP_Download(unsigned address, char *filename)
+{
+ unsigned thisSeconds, running, state;
+ int timeout, tickUpdate;
+
+ if (!address) {
+ // report last transfer information
+ printf("Last tftp transfer info --\r\n"
+ "address: 0x%x\r\n"
+ " size: 0x%x\r\n", lastAddress, lastSize);
+ return ;
+ }
+
+ if ((!localMACSet) || (!localIPAddr) || (!serverIPAddr))
+ return ;
+
+ if (!MAC_init) {
+ AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_EMAC;
+
+ AT91C_BASE_PIOA->PIO_ASR =
+ AT91C_PA14_ERXER |
+ AT91C_PA12_ERX0 |
+ AT91C_PA13_ERX1 |
+ AT91C_PA8_ETXEN |
+ AT91C_PA16_EMDIO |
+ AT91C_PA9_ETX0 |
+ AT91C_PA10_ETX1 |
+ AT91C_PA11_ECRS_ECRSDV |
+ AT91C_PA15_EMDC |
+ AT91C_PA7_ETXCK_EREFCK;
+ AT91C_BASE_PIOA->PIO_BSR = 0;
+ AT91C_BASE_PIOA->PIO_PDR =
+ AT91C_PA14_ERXER |
+ AT91C_PA12_ERX0 |
+ AT91C_PA13_ERX1 |
+ AT91C_PA8_ETXEN |
+ AT91C_PA16_EMDIO |
+ AT91C_PA9_ETX0 |
+ AT91C_PA10_ETX1 |
+ AT91C_PA11_ECRS_ECRSDV |
+ AT91C_PA15_EMDC |
+ AT91C_PA7_ETXCK_EREFCK;
+ AT91C_BASE_PIOB->PIO_ASR = 0;
+ AT91C_BASE_PIOB->PIO_BSR =
+ AT91C_PB12_ETX2 |
+ AT91C_PB13_ETX3 |
+ AT91C_PB14_ETXER |
+ AT91C_PB15_ERX2 |
+ AT91C_PB16_ERX3 |
+ AT91C_PB17_ERXDV |
+ AT91C_PB18_ECOL |
+ AT91C_PB19_ERXCK;
+ AT91C_BASE_PIOB->PIO_PDR =
+ AT91C_PB12_ETX2 |
+ AT91C_PB13_ETX3 |
+ AT91C_PB14_ETXER |
+ AT91C_PB15_ERX2 |
+ AT91C_PB16_ERX3 |
+ AT91C_PB17_ERXDV |
+ AT91C_PB18_ECOL |
+ AT91C_PB19_ERXCK;
+ MAC_init = 1;
+ }
+
+ AT91F_EmacEntry();
+
+ GetServerAddress();
+ lastAddress = address;
+ dlAddress = (char*)address;
+ lastSize = 0;
+ running = 1;
+ state = TFTP_WAITING_SERVER_MAC;
+ timeout = 10;
+ thisSeconds = GetSeconds();
+ serverPort = SWAP16(69);
+ localPort++; /* In network byte order, but who cares */
+ ackBlock = -1;
+
+ while (running && timeout) {
+
+ CheckForNewPacket();
+
+ tickUpdate = 0;
+
+ if (thisSeconds != GetSeconds()) {
+ tickUpdate = 1;
+ --timeout;
+ thisSeconds = GetSeconds();
+ }
+
+ switch (state) {
+
+ case TFTP_WAITING_SERVER_MAC:
+ if (serverMACSet) {
+ state = TFTP_SEND_REQUEST;
+ break;
+ }
+
+ if (tickUpdate)
+ GetServerAddress();
+ break;
+
+ case TFTP_SEND_REQUEST:
+ // send request for file
+ if (ackBlock != -1) {
+ state = TFTP_GET_DATA;
+ break;
+ }
+
+ if (tickUpdate)
+ TFTP_RequestFile(filename);
+ break;
+
+ case TFTP_GET_DATA:
+ // receiving data
+ if (ackBlock == -2) {
+ state = TFTP_COMPLETE;
+ break;
+ }
+ break;
+
+ case TFTP_COMPLETE:
+ default:
+ running = 0;
+ break;
+ }
+ }
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void EMAC_Init(void)
+ * This global function initializes variables used in tftp transfers.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+EMAC_Init(void)
+{
+ p_rxBD = (receive_descriptor_t*)RX_BUFFER_START;
+ localMACSet = 0;
+ serverMACSet = 0;
+ localPort = SWAP16(0x8002);
+ lastAddress = 0;
+ lastSize = 0;
+ MAC_init = 0;
+}
diff --git a/sys/boot/arm/at91/libat91/emac.h b/sys/boot/arm/at91/libat91/emac.h
new file mode 100644
index 0000000..ca5862a
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/emac.h
@@ -0,0 +1,122 @@
+/******************************************************************************
+ *
+ * Filename: emac.h
+ *
+ * Definition of routine to set the MAC address.
+ *
+ * Revision information:
+ *
+ * 28AUG2004 kb_admin initial creation
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+
+#ifndef _EMAC_H_
+#define _EMAC_H_
+
+extern void SetMACAddress(unsigned low_address, unsigned high_address);
+extern void SetServerIPAddress(unsigned address);
+extern void SetLocalIPAddress(unsigned address);
+extern void EMAC_Init(void);
+extern void TFTP_Download(unsigned address, char *filename);
+
+#define MAX_RX_PACKETS 8
+#define RX_PACKET_SIZE 1536
+#define RX_BUFFER_START 0x21000000
+#define RX_DATA_START (RX_BUFFER_START + (8 * MAX_RX_PACKETS))
+
+#define ARP_REQUEST 0x0001
+#define ARP_REPLY 0x0002
+#define PROTOCOL_ARP 0x0806
+#define PROTOCOL_IP 0x0800
+#define PROTOCOL_UDP 0x11
+
+#define SWAP16(x) ((((x) & 0xff) << 8) | ((x) >> 8))
+
+typedef struct {
+ unsigned address;
+ unsigned size;
+} receive_descriptor_t;
+
+typedef struct {
+
+ unsigned char dest_mac[6];
+
+ unsigned char src_mac[6];
+
+ unsigned short frame_type;
+ unsigned short hard_type;
+ unsigned short prot_type;
+ unsigned char hard_size;
+ unsigned char prot_size;
+
+ unsigned short operation;
+
+ unsigned char sender_mac[6];
+ unsigned char sender_ip[4];
+
+ unsigned char target_mac[6];
+ unsigned char target_ip[4];
+
+} __attribute__((__packed__)) arp_header_t;
+
+typedef struct {
+ unsigned char ip_v_hl;
+ unsigned char ip_tos;
+ unsigned short ip_len;
+ unsigned short ip_id;
+ unsigned short ip_off;
+ unsigned char ip_ttl;
+ unsigned char ip_p;
+ unsigned short ip_sum;
+ unsigned char ip_src[4];
+ unsigned char ip_dst[4];
+} __attribute__((__packed__)) ip_header_t;
+
+typedef struct {
+ unsigned char dest_mac[6];
+ unsigned char src_mac[6];
+ unsigned short proto_mac;
+ unsigned short packet_length;
+ ip_header_t iphdr;
+} __attribute__((__packed__)) transmit_header_t;
+
+typedef struct {
+ unsigned short src_port;
+ unsigned short dst_port;
+ unsigned short udp_len;
+ unsigned short udp_cksum;
+} __attribute__((__packed__)) udp_header_t;
+
+typedef struct {
+ unsigned short opcode;
+ unsigned short block_num;
+ unsigned char data[512];
+} __attribute__((__packed__)) tftp_header_t;
+
+#define TFTP_RRQ_OPCODE 1
+#define TFTP_WRQ_OPCODE 2
+#define TFTP_DATA_OPCODE 3
+#define TFTP_ACK_OPCODE 4
+#define TFTP_ERROR_OPCODE 5
+
+#define TFTP_WAITING_SERVER_MAC 1
+#define TFTP_SEND_REQUEST 2
+#define TFTP_GET_DATA 3
+#define TFTP_COMPLETE 4
+
+/* MII registers definition */
+#define MII_STS_REG 0x01
+#define MII_STS2_REG 0x11
+
+#endif /* _EMAC_H_ */
diff --git a/sys/boot/arm/at91/libat91/env_vars.c b/sys/boot/arm/at91/libat91/env_vars.c
new file mode 100644
index 0000000..4c08fd8
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/env_vars.c
@@ -0,0 +1,207 @@
+/******************************************************************************
+ *
+ * Filename: env_vars.c
+ *
+ * Instantiation of environment variables, structures, and other globals.
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+#include "env_vars.h"
+#include "loader_prompt.h"
+#include "p_string.h"
+#include "eeprom.h"
+#include "lib.h"
+
+/******************************* GLOBALS *************************************/
+char boot_commands[MAX_BOOT_COMMANDS][MAX_INPUT_SIZE];
+
+char env_table[MAX_ENV_SIZE_BYTES];
+
+extern char BootCommandSection;
+
+/************************** PRIVATE FUNCTIONS ********************************/
+
+
+static int currentIndex;
+static int currentOffset;
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * int ReadCharFromEnvironment(char *)
+ * This private function reads characters from the enviroment variables
+ * to service the command prompt during auto-boot or just to setup the
+ * default environment. Returns positive value if valid character was
+ * set in the pointer. Returns negative value to signal input stream
+ * terminated. Returns 0 to indicate _wait_ condition.
+ * .KB_C_FN_DEFINITION_END
+ */
+static int
+ReadCharFromEnvironment(int timeout)
+{
+ int ch;
+
+ if (currentIndex < MAX_BOOT_COMMANDS) {
+ ch = boot_commands[currentIndex][currentOffset++];
+ if (ch == '\0' || (currentOffset >= MAX_INPUT_SIZE)) {
+ currentOffset = 0;
+ ++currentIndex;
+ }
+ return (ch);
+ }
+
+ return (-1);
+}
+
+
+/*************************** GLOBAL FUNCTIONS ********************************/
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void WriteCommandTable(void)
+ * This global function write the current command table to the non-volatile
+ * memory.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+WriteCommandTable(void)
+{
+ int i, size = MAX_ENV_SIZE_BYTES, copySize;
+ char *cPtr = env_table;
+
+ p_memset(env_table, 0, sizeof(env_table));
+
+ for (i = 0; i < MAX_BOOT_COMMANDS; ++i) {
+
+ copySize = p_strlen(boot_commands[i]);
+ size -= copySize + 1;
+
+ if (size < 0) {
+ continue;
+ }
+ p_memcpy(cPtr, boot_commands[i], copySize);
+ cPtr += copySize;
+ *cPtr++ = 0;
+ }
+
+ WriteEEPROM((unsigned)&BootCommandSection, env_table,
+ sizeof(env_table));
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void SetBootCommand(int index, char *command)
+ * This global function replaces the specified index with the string residing
+ * at command. Execute this function with a NULL string to clear the
+ * associated command index.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+SetBootCommand(int index, char *command)
+{
+ int i;
+
+ if ((unsigned)index < MAX_BOOT_COMMANDS) {
+
+ p_memset(boot_commands[index], 0, MAX_INPUT_SIZE);
+
+ if (!command)
+ return ;
+
+ for (i = 0; i < MAX_INPUT_SIZE; ++i) {
+ boot_commands[index][i] = command[i];
+ if (!(boot_commands[index][i]))
+ return;
+ }
+ }
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void DumpBootCommands(void)
+ * This global function displays the current boot commands.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+DumpBootCommands(void)
+{
+ int i, j;
+
+ for (i = 0; i < MAX_BOOT_COMMANDS; ++i) {
+ printf("0x%x : ", i);
+ for (j = 0; j < MAX_INPUT_SIZE; ++j) {
+ putchar(boot_commands[i][j]);
+ if (!(boot_commands[i][j]))
+ break;
+ }
+ printf("[E]\n\r");
+ }
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void LoadBootCommands(void)
+ * This global function loads the existing boot commands from raw format and
+ * coverts it to the standard, command-index format. Notice, the processed
+ * boot command table has much more space allocated than the actual table
+ * stored in non-volatile memory. This is because the processed table
+ * exists in RAM which is larger than the non-volatile space.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+LoadBootCommands(void)
+{
+ int index, j, size;
+ char *cPtr;
+
+ p_memset((char*)boot_commands, 0, sizeof(boot_commands));
+
+ cPtr = &BootCommandSection;
+
+ size = MAX_ENV_SIZE_BYTES;
+
+ for (index = 0; (index < MAX_BOOT_COMMANDS) && size; ++index) {
+ for (j = 0; (j < MAX_INPUT_SIZE) && size; ++j) {
+ size--;
+ boot_commands[index][j] = *cPtr++;
+ if (!(boot_commands[index][j])) {
+ break;
+ }
+ }
+ }
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void ExecuteEnvironmentFunctions(void)
+ * This global function executes applicable entries in the environment.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+ExecuteEnvironmentFunctions(void)
+{
+ currentIndex = 0;
+ currentOffset = 0;
+
+ DumpBootCommands();
+ Bootloader(ReadCharFromEnvironment);
+}
diff --git a/sys/boot/arm/at91/libat91/env_vars.h b/sys/boot/arm/at91/libat91/env_vars.h
new file mode 100644
index 0000000..c6e46b4
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/env_vars.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ *
+ * Filename: env_vars.h
+ *
+ * Definition of environment variables, structures, and other globals.
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+#ifndef _ENV_VARS_H_
+#define _ENV_VARS_H_
+
+/* each environment variable is a string following the standard command */
+/* definition used by the interactive loader in the following format: */
+/* <command> <parm1> <parm2> ... */
+/* all environment variables (or commands) are stored in a string */
+/* format: NULL-terminated. */
+/* this implies that commands can never utilize 0-values: actual 0, not */
+/* the string '0'. this is not an issue as the string '0' is handled */
+/* by the command parse routine. */
+
+/* the following defines the maximum size of the environment for */
+/* including variables. */
+/* this value must match that declared in the low-level file that */
+/* actually reserves the space for the non-volatile environment. */
+#define MAX_ENV_SIZE_BYTES 0x100
+
+#define MAX_BOOT_COMMANDS 10
+
+/* C-style reference section */
+#ifndef __ASSEMBLY__
+
+extern void WriteCommandTable(void);
+extern void SetBootCommand(int index, char *command);
+extern void DumpBootCommands(void);
+extern void LoadBootCommands(void);
+extern void ExecuteEnvironmentFunctions(void);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ENV_VARS_H_ */
diff --git a/sys/boot/arm/at91/boot0/lib.c b/sys/boot/arm/at91/libat91/getc.c
index 1f3e6e6..c86183b 100644
--- a/sys/boot/arm/at91/boot0/lib.c
+++ b/sys/boot/arm/at91/libat91/getc.c
@@ -34,23 +34,9 @@
* $FreeBSD$
*/
-#include "AT91RM9200.h"
+#include "at91rm9200.h"
#include "at91rm9200_lowlevel.h"
-
-/*
- * void putc(int ch)
- * Writes a character to the DBGU port. It assumes that DBGU has
- * already been initialized.
- */
-void
-putc(int ch)
-{
- AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU;
-
- while (!(pUSART->US_CSR & AT91C_US_TXRDY))
- continue;
- pUSART->US_THR = (ch & 0xFF);
-}
+#include "lib.h"
/*
* int getc(int seconds)
diff --git a/sys/boot/arm/at91/boot0/lib.h b/sys/boot/arm/at91/libat91/lib.h
index 535b719..73a1f47 100644
--- a/sys/boot/arm/at91/boot0/lib.h
+++ b/sys/boot/arm/at91/libat91/lib.h
@@ -28,6 +28,16 @@
#define ARM_BOOT_LIB_H
int getc(int);
-void putc(int);
+void putchar(int);
+void printf(const char *fmt,...);
+
+/* The following function write eeprom at ee_addr using data */
+/* from data_add for size bytes. */
+void ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size);
+void WriteEEPROM(unsigned ee_addr, char *data_addr, unsigned size);
+void InitEEPROM(void);
+
+/* XMODEM protocol */
+int xmodem_rx(char *dst);
#endif
diff --git a/sys/boot/arm/at91/libat91/loader_prompt.c b/sys/boot/arm/at91/libat91/loader_prompt.c
new file mode 100644
index 0000000..264765a
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/loader_prompt.c
@@ -0,0 +1,426 @@
+/******************************************************************************
+ *
+ * Filename: loader_prompt.c
+ *
+ * Instantiation of the interactive loader functions.
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ * 12JAN2005 kb_admin massive changes for tftp, strings, and more
+ * 05JUL2005 kb_admin save tag address, and set registers on boot
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+#include "at91rm9200_lowlevel.h"
+#include "p_string.h"
+#include "eeprom.h"
+#ifdef SUPPORT_TAG_LIST
+#include "tag_list.h"
+#endif
+#include "emac.h"
+#include "loader_prompt.h"
+#include "env_vars.h"
+#include "lib.h"
+
+
+/******************************* GLOBALS *************************************/
+
+
+/*********************** PRIVATE FUNCTIONS/DATA ******************************/
+
+static char inputBuffer[MAX_INPUT_SIZE];
+static int buffCount;
+
+// argv pointer are either NULL or point to locations in inputBuffer
+static char *argv[MAX_COMMAND_PARAMS];
+
+static char backspaceString[] = {0x8, ' ', 0x8, 0};
+
+static command_entry_t CommandTable[] = {
+ {COMMAND_COPY, "c"},
+ {COMMAND_DUMP, "d"},
+ {COMMAND_EXEC, "e"},
+ {COMMAND_HELP, "?"},
+ {COMMAND_LOCAL_IP, "ip"},
+ {COMMAND_MAC, "m"},
+ {COMMAND_SERVER_IP, "server_ip"},
+ {COMMAND_SET, "s"},
+#ifdef SUPPORT_TAG_LIST
+ {COMMAND_TAG, "t"},
+#endif
+ {COMMAND_TFTP, "tftp"},
+ {COMMAND_WRITE, "w"},
+ {COMMAND_XMODEM, "x"},
+ {COMMAND_FINAL_FLAG, 0}
+};
+
+static unsigned tagAddress;
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * unsigned BuildIP(void)
+ * This private function packs the test IP info to an unsigned value.
+ * .KB_C_FN_DEFINITION_END
+ */
+static unsigned
+BuildIP(void)
+{
+ return ((p_ASCIIToDec(argv[1]) << 24) |
+ (p_ASCIIToDec(argv[2]) << 16) |
+ (p_ASCIIToDec(argv[3]) << 8) |
+ p_ASCIIToDec(argv[4]));
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * int StringToCommand(char *cPtr)
+ * This private function converts a command string to a command code.
+ * .KB_C_FN_DEFINITION_END
+ */
+static int
+StringToCommand(char *cPtr)
+{
+ int i;
+
+ for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i)
+ if (!p_strcmp(CommandTable[i].c_string, cPtr))
+ return (CommandTable[i].command);
+
+ return (COMMAND_INVALID);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void RestoreSpace(int)
+ * This private function restores NULL characters to spaces in order to
+ * process the remaining args as a string. The number passed is the argc
+ * of the first entry to begin restoring space in the inputBuffer.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+RestoreSpace(int startArgc)
+{
+ char *cPtr;
+
+ for (startArgc++; startArgc < MAX_COMMAND_PARAMS; startArgc++) {
+ if ((cPtr = argv[startArgc]))
+ *(cPtr - 1) = ' ';
+ }
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * int BreakCommand(char *)
+ * This private function splits the buffer into separate strings as pointed
+ * by argv and returns the number of parameters (< 0 on failure).
+ * .KB_C_FN_DEFINITION_END
+ */
+static int
+BreakCommand(char *buffer)
+{
+ int pCount, cCount, state;
+
+ state = pCount = 0;
+ p_memset((char*)argv, 0, sizeof(argv));
+
+ for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) {
+
+ if (!state) {
+ /* look for next command */
+ if (!p_IsWhiteSpace(buffer[cCount])) {
+ argv[pCount++] = &buffer[cCount];
+ state = 1;
+ } else {
+ buffer[cCount] = 0;
+ }
+ } else {
+ /* in command, find next white space */
+ if (p_IsWhiteSpace(buffer[cCount])) {
+ buffer[cCount] = 0;
+ state = 0;
+ }
+ }
+
+ if (pCount >= MAX_COMMAND_PARAMS) {
+ return (-1);
+ }
+ }
+
+ return (pCount);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void ParseCommand(char *)
+ * This private function executes matching functions.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+ParseCommand(char *buffer)
+{
+ int argc;
+
+ if ((argc = BreakCommand(buffer)) < 1) {
+ return ;
+ }
+
+ switch (StringToCommand(argv[0])) {
+
+ case COMMAND_COPY:
+ {
+ // "c <to> <from> <size in bytes>"
+ // copy memory
+
+ char *to, *from;
+ unsigned size;
+
+ if (argc > 3) {
+ to = (char *)p_ASCIIToHex(argv[1]);
+ from = (char *)p_ASCIIToHex(argv[2]);
+ size = p_ASCIIToHex(argv[3]);
+ p_memcpy(to, from, size);
+ }
+
+ }
+ break;
+
+ case COMMAND_DUMP:
+ // display boot commands
+ DumpBootCommands();
+ break;
+
+ case COMMAND_EXEC:
+ {
+ // "e <address>"
+ // execute at address
+
+ void (*execAddr)(unsigned, unsigned, unsigned);
+
+ if (argc > 1) {
+ /* in future, include machtypes (MACH_KB9200 = 612) */
+ execAddr = (void (*)(unsigned, unsigned, unsigned))
+ p_ASCIIToHex(argv[1]);
+ (*execAddr)(0, 612, tagAddress);
+ }
+
+ }
+ break;
+
+ case COMMAND_TFTP:
+ {
+ // "tftp <local_dest_addr filename>"
+ // tftp download
+
+ unsigned address = 0;
+
+ if (argc > 2)
+ address = p_ASCIIToHex(argv[1]);
+
+ TFTP_Download(address, argv[2]);
+
+ }
+ break;
+
+ case COMMAND_SERVER_IP:
+ // "server_ip <server IP 192 200 1 20>"
+ // set download server address
+
+ if (argc > 4)
+ SetServerIPAddress(BuildIP());
+ break;
+
+ case COMMAND_HELP:
+ // dump command info
+ printf("Commands:\r\n"
+ "\tc\r\n"
+ "\td\r\n"
+ "\te\r\n"
+ "\tip\r\n"
+ "\tserver_ip\r\n"
+ "\tm\r\n"
+ "\ttftp\r\n"
+ "\ts\r\n"
+#ifdef SUPPORT_TAG_LIST
+ "\tt\r\n"
+#endif
+ "\tw\r\n"
+ "\tx\r\n");
+ break;
+
+ case COMMAND_LOCAL_IP:
+ // "local_ip <local IP 192 200 1 21>
+ // set ip of this module
+
+ if (argc > 4)
+ SetLocalIPAddress(BuildIP());
+ break;
+
+ case COMMAND_MAC:
+ {
+ // "m <mac address 12 34 56 78 9a bc>
+ // set mac address using 6 byte values
+
+ unsigned low_addr, high_addr;
+
+ if (argc > 6) {
+
+ low_addr = (p_ASCIIToHex(argv[4]) << 24) |
+ (p_ASCIIToHex(argv[3]) << 16) |
+ (p_ASCIIToHex(argv[2]) << 8) |
+ p_ASCIIToHex(argv[1]);
+ high_addr =
+ (p_ASCIIToHex(argv[6]) << 8) |
+ p_ASCIIToHex(argv[5]);
+ SetMACAddress(low_addr, high_addr);
+ }
+
+ }
+ break;
+
+ case COMMAND_SET:
+ {
+ // s <index> <new boot command>
+ // set the boot command at index (0-based)
+
+ unsigned index;
+
+ if (argc > 1) {
+ RestoreSpace(2);
+ index = p_ASCIIToHex(argv[1]);
+ SetBootCommand(index, argv[2]);
+ }
+
+ }
+ break;
+
+#ifdef SUPPORT_TAG_LIST
+ case COMMAND_TAG:
+ {
+ // t <address> <boot command line>
+ // create tag-list for linux boot
+
+ if (argc > 2) {
+ RestoreSpace(2);
+ tagAddress = p_ASCIIToHex(argv[1]);
+ InitTagList(argv[2], (void*)tagAddress);
+ }
+
+ }
+ break;
+#endif
+
+ case COMMAND_WRITE:
+ // write the command table to non-volatile
+
+ WriteCommandTable();
+ break;
+
+ case COMMAND_XMODEM:
+ {
+ // "x <address>"
+ // download X-modem record at address
+
+ char *destAddr = 0;
+
+ if (argc > 1) {
+ destAddr = (char *)p_ASCIIToHex(argv[1]);
+ xmodem_rx(destAddr);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ printf("\r\n");
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void ServicePrompt(char)
+ * This private function process each character checking for valid commands.
+ * This function is only executed if the character is considered valid.
+ * Each command is terminated with NULL (0) or '\r'.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void ServicePrompt(char p_char) {
+
+ if (p_char == '\r') {
+ p_char = 0;
+
+ }
+
+ if (p_char != 0x8) {
+ if (buffCount < MAX_INPUT_SIZE-1) {
+
+ inputBuffer[buffCount] = p_char;
+ ++buffCount;
+ putchar(p_char);
+ }
+
+ } else if (buffCount) {
+
+ /* handle backspace BS */
+ --buffCount;
+ inputBuffer[buffCount] = 0;
+ printf(backspaceString);
+ return ;
+ }
+
+ if (!p_char) {
+ printf("\r\n");
+ ParseCommand(inputBuffer);
+ p_memset(inputBuffer, 0, MAX_INPUT_SIZE);
+ buffCount = 0;
+ printf("\r\n>");
+ }
+}
+
+
+/* ************************** GLOBAL FUNCTIONS ********************************/
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void Bootloader(void *inputFunction)
+ * This global function is the entry point for the bootloader. If the
+ * inputFunction pointer is NULL, the loader input will be serviced from
+ * the uart. Otherwise, inputFunction is called to get characters which
+ * the loader will parse.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+Bootloader(int(*inputFunction)(int))
+{
+ int ch = 0;
+
+ p_memset((void*)inputBuffer, 0, sizeof(inputBuffer));
+
+ buffCount = 0;
+ if (!inputFunction) {
+ inputFunction = getc;
+ }
+
+ printf("\r\n>");
+
+ while (ch >= 0)
+ if ((ch = ((*inputFunction)(0))) > 0)
+ ServicePrompt(ch);
+}
diff --git a/sys/boot/arm/at91/libat91/loader_prompt.h b/sys/boot/arm/at91/libat91/loader_prompt.h
new file mode 100644
index 0000000..0223340
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/loader_prompt.h
@@ -0,0 +1,55 @@
+/******************************************************************************
+ *
+ * Filename: loader_prompt.h
+ *
+ * Definition of the interactive loader functions.
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+#ifndef _LOADER_PROMPT_H_
+#define _LOADER_PROMPT_H_
+
+#define MAX_INPUT_SIZE 256
+#define MAX_COMMAND_PARAMS 10
+
+enum {
+ COMMAND_INVALID = 0,
+ COMMAND_COPY,
+ COMMAND_DUMP,
+ COMMAND_EXEC,
+ COMMAND_HELP,
+ COMMAND_LOCAL_IP,
+ COMMAND_MAC,
+ COMMAND_SERVER_IP,
+ COMMAND_SET,
+ COMMAND_TAG,
+ COMMAND_TFTP,
+ COMMAND_WRITE,
+ COMMAND_XMODEM,
+ COMMAND_FINAL_FLAG
+} e_cmd_t;
+
+
+typedef struct {
+ int command;
+ const char *c_string;
+} command_entry_t;
+
+void EnterInteractiveBootloader(int(*inputFunction)(int));
+void Bootloader(int(*inputFunction)(int));
+
+#endif /* _LOADER_PROMPT_H_ */
diff --git a/sys/boot/arm/at91/libat91/p_string.c b/sys/boot/arm/at91/libat91/p_string.c
new file mode 100644
index 0000000..743b011
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/p_string.c
@@ -0,0 +1,210 @@
+/******************************************************************************
+ *
+ * Filename: p_string.c
+ *
+ * Instantiation of basic string operations to prevent inclusion of full
+ * string library. These are simple implementations not necessarily optimized
+ * for speed, but rather to show intent.
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ * 12JAN2005 kb_admin minor updates
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+#include "p_string.h"
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * int p_IsWhiteSpace(char)
+ * This global function returns true if the character is not considered
+ * a non-space character.
+ * .KB_C_FN_DEFINITION_END
+ */
+int
+p_IsWhiteSpace(char cValue)
+{
+ return ((cValue == ' ') ||
+ (cValue == '\t') ||
+ (cValue == 0) ||
+ (cValue == '\r') ||
+ (cValue == '\n'));
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * unsigned p_HexCharValue(char)
+ * This global function returns the decimal value of the validated hex char.
+ * .KB_C_FN_DEFINITION_END
+ */
+unsigned
+p_HexCharValue(char cValue)
+{
+ if (cValue < ('9' + 1))
+ return (cValue - '0');
+ if (cValue < ('F' + 1))
+ return (cValue - 'A' + 10);
+ return (cValue - 'a' + 10);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void p_memset(char *buffer, char value, int size)
+ * This global function sets memory at the pointer for the specified
+ * number of bytes to value.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+p_memset(char *buffer, char value, int size)
+{
+ while (size--)
+ *buffer++ = value;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * int p_strlen(char *)
+ * This global function returns the number of bytes starting at the pointer
+ * before (not including) the string termination character ('/0').
+ * .KB_C_FN_DEFINITION_END
+ */
+int
+p_strlen(const char *buffer)
+{
+ int len = 0;
+ if (buffer)
+ while (buffer[len])
+ len++;
+ return (len);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * char *p_strcpy(char *to, char *from)
+ * This global function returns a pointer to the end of the destination string
+ * after the copy operation (after the '/0').
+ * .KB_C_FN_DEFINITION_END
+ */
+char *
+p_strcpy(char *to, const char *from)
+{
+ while (*from)
+ *to++ = *from++;
+ *to++ = '\0';
+ return (to);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * unsigned p_ASCIIToHex(char *)
+ * This global function set the unsigned value equal to the converted
+ * hex number passed as a string. No error checking is performed; the
+ * string must be valid hex value, point at the start of string, and be
+ * NULL-terminated.
+ * .KB_C_FN_DEFINITION_END
+ */
+unsigned
+p_ASCIIToHex(const char *buf)
+{
+ unsigned lValue = 0;
+
+ if ((*buf == '0') && ((buf[1] == 'x') || (buf[1] == 'X')))
+ buf += 2;
+
+ while (*buf) {
+ lValue <<= 4;
+ lValue += p_HexCharValue(*buf++);
+ }
+ return (lValue);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * unsigned p_ASCIIToDec(char *)
+ * This global function set the unsigned value equal to the converted
+ * decimal number passed as a string. No error checking is performed; the
+ * string must be valid decimal value, point at the start of string, and be
+ * NULL-terminated.
+ * .KB_C_FN_DEFINITION_END
+ */
+unsigned
+p_ASCIIToDec(const char *buf)
+{
+ unsigned v = 0;
+
+ while (*buf) {
+ v *= 10;
+ v += (*buf++) - '0';
+ }
+ return (v);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void p_memcpy(char *, char *, unsigned)
+ * This global function copies data from the first pointer to the second
+ * pointer for the specified number of bytes.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+p_memcpy(char *to, const char *from, unsigned size)
+{
+ while (size--)
+ *to++ = *from++;
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * int p_memcmp(char *to, char *from, unsigned size)
+ * This global function compares data at to against data at from for
+ * size bytes. Returns 0 if the locations are equal. size must be
+ * greater than 0.
+ * .KB_C_FN_DEFINITION_END
+ */
+int
+p_memcmp(const char *to, const char *from, unsigned size)
+{
+ while ((--size) && (*to++ == *from++))
+ continue;
+
+ return (*to != *from);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * int p_strcmp(char *to, char *from)
+ * This global function compares string at to against string at from.
+ * Returns 0 if the locations are equal.
+ * .KB_C_FN_DEFINITION_END
+ */
+int
+p_strcmp(const char *to, const char *from)
+{
+
+ while (*to && *from && (*to == *from)) {
+ ++to;
+ ++from;
+ }
+
+ return (!((!*to) && (*to == *from)));
+}
diff --git a/sys/boot/arm/at91/libat91/p_string.h b/sys/boot/arm/at91/libat91/p_string.h
new file mode 100644
index 0000000..d4461b3
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/p_string.h
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ * Filename: p_string.h
+ *
+ * Definition of basic, private, string operations to prevent inclusion of full
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+#ifndef _P_STRING_H_
+#define _P_STRING_H_
+
+#define ToASCII(x) ((x > 9) ? (x + 'A' - 0xa) : (x + '0'))
+
+int p_IsWhiteSpace(char cValue);
+unsigned p_HexCharValue(char cValue);
+void p_memset(char *buffer, char value, int size);
+int p_strlen(const char *buffer);
+char *p_strcpy(char *to, const char *from);
+unsigned p_ASCIIToHex(const char *buf);
+unsigned p_ASCIIToDec(const char *buf);
+void p_memcpy(char *to, const char *from, unsigned size);
+int p_memcmp(const char *to, const char *from, unsigned size);
+int p_strcmp(const char *to, const char *from);
+
+#endif /* _P_STRING_H_ */
diff --git a/sys/boot/arm/at91/libat91/printf.c b/sys/boot/arm/at91/libat91/printf.c
new file mode 100644
index 0000000..81b48c5
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/printf.c
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 1998 Robert Nordier
+ * All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdarg.h>
+#include "lib.h"
+
+void
+printf(const char *fmt,...)
+{
+ va_list ap;
+ const char *hex = "0123456789abcdef";
+ char buf[10];
+ char *s;
+ unsigned u;
+ int c;
+
+ va_start(ap, fmt);
+ while ((c = *fmt++)) {
+ if (c == '%') {
+ c = *fmt++;
+ switch (c) {
+ case 'c':
+ putchar(va_arg(ap, int));
+ continue;
+ case 's':
+ for (s = va_arg(ap, char *); *s; s++)
+ putchar(*s);
+ continue;
+ case 'u':
+ u = va_arg(ap, unsigned);
+ s = buf;
+ do
+ *s++ = '0' + u % 10U;
+ while (u /= 10U);
+ dumpbuf:;
+ while (--s >= buf)
+ putchar(*s);
+ continue;
+ case 'x':
+ u = va_arg(ap, unsigned);
+ s = buf;
+ do
+ *s++ = hex[u & 0xfu];
+ while (u >>= 4);
+ goto dumpbuf;
+ }
+ }
+ putchar(c);
+ }
+ va_end(ap);
+
+ return;
+}
diff --git a/sys/boot/arm/at91/boot0/xmodem.h b/sys/boot/arm/at91/libat91/putchar.c
index bcc156c..137c2e3 100644
--- a/sys/boot/arm/at91/boot0/xmodem.h
+++ b/sys/boot/arm/at91/libat91/putchar.c
@@ -21,12 +21,34 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
+ * This software is derived from software provided by kwikbyte without
+ * copyright as follows:
+ *
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ *
* $FreeBSD$
*/
-#ifndef BOOT_ARM_XMODEM_H
-#define BOOT_ARM_XMODEM_H
+#include "at91rm9200.h"
+#include "at91rm9200_lowlevel.h"
+#include "lib.h"
-int xmodem_rx(char *dst);
+/*
+ * void putchar(int ch)
+ * Writes a character to the DBGU port. It assumes that DBGU has
+ * already been initialized.
+ */
+void
+putchar(int ch)
+{
+ AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU;
-#endif /* BOOT_ARM_XMODEM_H */
+ while (!(pUSART->US_CSR & AT91C_US_TXRDY))
+ continue;
+ pUSART->US_THR = (ch & 0xFF);
+}
diff --git a/sys/boot/arm/at91/libat91/tag_list.c b/sys/boot/arm/at91/libat91/tag_list.c
new file mode 100644
index 0000000..41b150c
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/tag_list.c
@@ -0,0 +1,79 @@
+/******************************************************************************
+ *
+ * Filename: tag_list.c
+ *
+ * Instantiation of basic routines that create linux-boot tag list.
+ *
+ * Revision information:
+ *
+ * 22AUG2004 kb_admin initial creation
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+/******************************* GLOBALS *************************************/
+
+/********************** PRIVATE FUNCTIONS/DATA/DEFINES ***********************/
+
+#define u32 unsigned
+#define u16 unsigned short
+#define u8 unsigned char
+
+#include "/usr/src/arm/linux/include/asm/setup.h"
+
+#define PAGE_SIZE 0x1000
+#define MEM_SIZE 0x2000000
+#define PHYS_OFFSET 0x20000000
+
+/*************************** GLOBAL FUNCTIONS ********************************/
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void InitTagList(char*, void *)
+ * This global function populates a linux-boot style tag list from the
+ * string passed in the pointer at the location specified.
+ * .KB_C_FN_DEFINITION_END
+ */
+void InitTagList(char *parms, void *output) {
+
+ char *src, *dst;
+ struct tag *tagList = (struct tag*)output;
+
+ tagList->hdr.size = tag_size(tag_core);
+ tagList->hdr.tag = ATAG_CORE;
+ tagList->u.core.flags = 1;
+ tagList->u.core.pagesize = PAGE_SIZE;
+ tagList->u.core.rootdev = 0xff;
+ tagList = tag_next(tagList);
+
+ tagList->hdr.size = tag_size(tag_mem32);
+ tagList->hdr.tag = ATAG_MEM;
+ tagList->u.mem.size = MEM_SIZE;
+ tagList->u.mem.start = PHYS_OFFSET;
+ tagList = tag_next(tagList);
+
+ tagList->hdr.size = tag_size(tag_cmdline);
+ tagList->hdr.tag = ATAG_CMDLINE;
+
+ src = parms;
+ dst = tagList->u.cmdline.cmdline;
+ while (*src) {
+ *dst++ = *src++;
+ }
+ *dst = 0;
+
+ tagList->hdr.size += ((unsigned)(src - parms) + 1) / sizeof(unsigned);
+ tagList = tag_next(tagList);
+
+ tagList->hdr.size = 0;
+ tagList->hdr.tag = ATAG_NONE;
+}
diff --git a/sys/boot/arm/at91/libat91/tag_list.h b/sys/boot/arm/at91/libat91/tag_list.h
new file mode 100644
index 0000000..6fa4ea9
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/tag_list.h
@@ -0,0 +1,28 @@
+/******************************************************************************
+ *
+ * Filename: tag_list.h
+ *
+ * Definition of basic routines that create linux-boot tag list.
+ *
+ * Revision information:
+ *
+ * 22AUG2004 kb_admin initial creation
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+#ifndef _TAG_LIST_H_
+#define _TAG_LIST_H_
+
+extern void InitTagList(char *parms, void*);
+
+#endif /* _TAG_LIST_H_ */
diff --git a/sys/boot/arm/at91/boot0/xmodem.c b/sys/boot/arm/at91/libat91/xmodem.c
index 8781187..c3903aa 100644
--- a/sys/boot/arm/at91/boot0/xmodem.c
+++ b/sys/boot/arm/at91/libat91/xmodem.c
@@ -81,11 +81,11 @@ GetRecord(char blocknum, char *dest)
goto err;
if (((ch = getc(1)) == -1) || ((ch & 0xff) != (chk & 0xFF)))
goto err;
- putc(ACK);
+ putchar(ACK);
return (1);
err:;
- putc(CAN);
+ putchar(CAN);
// We should allow for resend, but we don't.
return (0);
}
@@ -107,11 +107,11 @@ xmodem_rx(char *dest)
while (1) {
if (starting)
- putc('C');
+ putchar('C');
if (((ch = getc(1)) == -1) || (ch != SOH && ch != EOT))
continue;
if (ch == EOT) {
- putc(ACK);
+ putchar(ACK);
return (dest - startAddress);
}
starting = 0;
diff --git a/sys/boot/arm/at91/linker.cfg b/sys/boot/arm/at91/linker.cfg
new file mode 100644
index 0000000..40ae7bf
--- /dev/null
+++ b/sys/boot/arm/at91/linker.cfg
@@ -0,0 +1,291 @@
+/*******************************************************************************
+ *
+ * Filename: linker.cfg
+ *
+ * linker config file used for internal RAM or eeprom images at address 0.
+ *
+ * Revision information:
+ *
+ * 20AUG2004 kb_admin initial creation
+ * 12JAN2005 kb_admin move data to SDRAM
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ ******************************************************************************/
+OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
+ "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(start)
+ SEARCH_DIR(/usr/local/arm/2.95.3/arm-linux/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0;
+ .text :
+ {
+ *(.text)
+ *(.text.*)
+ *(.stub)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t.*)
+ *(.glue_7t) *(.glue_7)
+ }
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text :
+ {
+ *(.rel.text)
+ *(.rel.text.*)
+ *(.rel.gnu.linkonce.t.*)
+ }
+ .rela.text :
+ {
+ *(.rela.text)
+ *(.rela.text.*)
+ *(.rela.gnu.linkonce.t.*)
+ }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.rodata :
+ {
+ *(.rel.rodata)
+ *(.rel.rodata.*)
+ *(.rel.gnu.linkonce.r.*)
+ }
+ .rela.rodata :
+ {
+ *(.rela.rodata)
+ *(.rela.rodata.*)
+ *(.rela.gnu.linkonce.r.*)
+ }
+ .rel.data :
+ {
+ *(.rel.data)
+ *(.rel.data.*)
+ *(.rel.gnu.linkonce.d.*)
+ }
+ .rela.data :
+ {
+ *(.rela.data)
+ *(.rela.data.*)
+ *(.rela.gnu.linkonce.d.*)
+ }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.sdata :
+ {
+ *(.rel.sdata)
+ *(.rel.sdata.*)
+ *(.rel.gnu.linkonce.s.*)
+ }
+ .rela.sdata :
+ {
+ *(.rela.sdata)
+ *(.rela.sdata.*)
+ *(.rela.gnu.linkonce.s.*)
+ }
+ .rel.sbss :
+ {
+ *(.rel.sbss)
+ *(.rel.sbss.*)
+ *(.rel.gnu.linkonce.sb.*)
+ }
+ .rela.sbss :
+ {
+ *(.rela.sbss)
+ *(.rela.sbss.*)
+ *(.rel.gnu.linkonce.sb.*)
+ }
+ .rel.sdata2 :
+ {
+ *(.rel.sdata2)
+ *(.rel.sdata2.*)
+ *(.rel.gnu.linkonce.s2.*)
+ }
+ .rela.sdata2 :
+ {
+ *(.rela.sdata2)
+ *(.rela.sdata2.*)
+ *(.rela.gnu.linkonce.s2.*)
+ }
+ .rel.sbss2 :
+ {
+ *(.rel.sbss2)
+ *(.rel.sbss2.*)
+ *(.rel.gnu.linkonce.sb2.*)
+ }
+ .rela.sbss2 :
+ {
+ *(.rela.sbss2)
+ *(.rela.sbss2.*)
+ *(.rela.gnu.linkonce.sb2.*)
+ }
+ .rel.bss :
+ {
+ *(.rel.bss)
+ *(.rel.bss.*)
+ *(.rel.gnu.linkonce.b.*)
+ }
+ .rela.bss :
+ {
+ *(.rela.bss)
+ *(.rela.bss.*)
+ *(.rela.gnu.linkonce.b.*)
+ }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init :
+ {
+ KEEP (*(.init))
+ } =0
+ .plt : { *(.plt) }
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) }
+ .sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) }
+ .data :
+ {
+ __data_start = . ;
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ . = 0x21200000;
+ .eh_frame : { KEEP (*(.eh_frame)) }
+ .gcc_except_table : { *(.gcc_except_table) }
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ /* We don't want to include the .ctor section from
+ from the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .got : { *(.got.plt) *(.got) }
+ .dynamic : { *(.dynamic) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata :
+ {
+ *(.sdata)
+ *(.sdata.*)
+ *(.gnu.linkonce.s.*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ __bss_start__ = .;
+ .sbss :
+ {
+ PROVIDE (__sbss_start = .);
+ PROVIDE (___sbss_start = .);
+ *(.dynsbss)
+ *(.sbss)
+ *(.sbss.*)
+ *(.gnu.linkonce.sb.*)
+ *(.scommon)
+ PROVIDE (__sbss_end = .);
+ PROVIDE (___sbss_end = .);
+ }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss)
+ *(.bss.*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections. */
+ . = ALIGN(32 / 8);
+ }
+ . = ALIGN(32 / 8);
+ _end = .;
+ _bss_end__ = . ; __bss_end__ = . ; __end__ = . ;
+ PROVIDE (end = .);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* These must appear regardless of . */
+}
OpenPOWER on IntegriCloud