MFC Loader Fixes 2017q4p6: r324649,r324650,r324651,r324652,r324653,r324654,
r324700,r324702,r324709,r324717,r324719,r324841,r324842,r324843,r324845, r324850,r324876,r324877,r324878,r324879,r324880,r324881,r324883,r324980, r324981,r324982,r324995,r325014,r325093,r325094,r325114,r325170,r325171, r325172,r325173,r325174,r325175,r325176,r325248,r325286,r325310,r325332, r325338,r325339,r325376,r325377,r325379,r325380,r325382,r325478,r325479, r325480,r325482,r325483,r325484,r325485,r325556,r325641,r325681,r325685, r325686,r325687,r325688,r325689,r325690,r325691,r325692,r325693,r325694, r325743,r325744,r325748,r325775,r325779,r325780 r324649: Move common/Makefile.inc to sys/boot/loader.mk. r324650: tweak style r324651: create defs.mk for common definitions r324652: Move all the ficl common code into ficl.mk r324653: LOADER_foo_SUPPORTED r324654: Explicitly inlcude SYSDIR in the include path r324700: loader: initialize dv_cleanup in md.c to eliminate clang warning r324702: We need to include disk.o in libuboot.a when we're building with support for disk access. r324709: Revert "Unify boot1 with loader" change r324646 r324717: libsa/ip.c: misplaced comment, ip_v is half char, not ip_p r324719: libsa/ip: stop read loop on bad fragments r324841: Use BOOTDIR more consistently in defs.mk rather than repeat sys/boot. r324842: Introduce BOOTOBJ: The top level object directory for the boot tree r324843: Stopgap fix to the mistmatch between LOADER_GELI_SUPPORT and LOADER_NO_GELI_SUPPORT. r324845: Use BOOTOBJ and BOOTDIR to find geli includes and libraries. r324850: Define LIBSA32 to LIBSA on i386 to fix build. r324876: Move fdt and uboot defines into common uboot.mk. r324877: End source directories with SRC rather than a hodgepodge of names r324878: Make at91 boot loader compile again. r324879: Prefer SRCTOP paths for bits we're grabbing from libc. r324880: Use BOOTSRC here. r324881: Use SYSDIR instead of ${.CURDIR}/../..<etc>/sys. r324883: Use preferred defined paths, rather than relative paths in fdt. r324980: Use BOOTDIR consistently. r324981: Move BINDIR definition to defs.mk, and override where it isn't /boot r324982: Remove sys/boot/arm/at91 and ixp425 r324995: loader.efi: Make framebuffer commands available for arm64 r325014: Add a 'place holder' arm struct efi_fb until a real one comes r325093: Define new EFI variables r325094: Cleanup non-arch Makefiles r325114: Use defs.mk defins in most MD code r325170: Use defs.mk values for userboot r325171: Use defs.mk name and prefer bsd.init.mk r325172: Remove the -nostdlib stuff I added. Instead, fix LDFLAGS to be honored correctly with the new Makefile.inc include order. r325173: We don't need to build a special ficl for userboot. r325174: Minor cleanup r325175: For amd64, compile both zfs and zfs32 libraries. r325176: Actually add zfs32/Makefile r325248: loader ptblread() is broken with >512B sectors r325286: efipart_strategy is using wrong offset with >512B sectors r325310: zfs.c:vdev_read() needs to be careful about large sectors r325332: loader: re-enable gzip support for x86 r325338: loader: fix BOOTSRC -> BOOTOBJ in a library path r325339: This used to have bzip2 support too. r325376: WIP: centralize machine links r325377: mostly libsa r325379: Revert "mostly libsa" r325380: Revert "WIP: centralize machine links" r325382: Cleanup stray libstand names to be libsa names. r325478: Powerpc is a 32-bit boot loader. r325479: Define LIBFICL32 to be libficl.a on i386 and libficl32.a on amd64. r325480: Use DO32 for all the places that we need to flag we're building a 32-bit version of a library. r325482: Move machine and other link creation to defs.mk r325483: MACHINE can never be powerpc64, so cleanup code that thinks it can. r325484: Prefer bsd.init.mk to src.opts.mk r325485: Centralize all 32-bit builds on 64-bit platform stuff. r325556: loader: set options before including bsd.init.mk r325641: loader.efi: efi_devpath_is_prefix should return bool r325681: boot1: avoid using NULL device path r325685: libsa32 isn't needed for i386. It's already a 32-bit platform. r325686: Simplify this if to a direct assignment. r325687: Remove all the empty help files from the powerpc build. r325688: FDT support doesn't make sense for ps3, remove it. r325689: Remove LOADER_FDT_SUPPORT as a Makefile variable. r325690: Remove LOADER_ZFS_SUPPORT as a Makefile variable r325691: Remove useless PNP define here. r325692: Replace LOADER_FIREWIRE_SUPPORT variable r325693: Move LOADER_{NO,}_GELI_SUPPORT to MK_LOADER_GELI r325694: Install the 4th files in sys/boot/forth instead of each loader r325743: Make sure the proper loader.rc gets installed. r325744: boot1: also check for NULL device r325748: Use proper include file. r325775: Add loader.conf to the list of files that are MD. r325779: Add /boot/dts to the list of default modules. r325780: Don't add /boot/dt*s* but /boot/dt*b*. Stupid think-o.
This commit is contained in:
parent
0354b736fe
commit
d100639560
5
UPDATING
5
UPDATING
@ -16,6 +16,11 @@ from older versions of FreeBSD, try WITHOUT_CLANG and WITH_GCC to bootstrap to
|
||||
the tip of head, and then rebuild without this option. The bootstrap process
|
||||
from older version of current across the gcc/clang cutover is a bit fragile.
|
||||
|
||||
20180211:
|
||||
The LOADER_FIREWIRE_SUPPORT build variable as been renamed to
|
||||
WITH/OUT_LOADER_FIREWIRE. LOADER_{NO_,}GELI_SUPPORT has been renamed
|
||||
to WITH/OUT_LOADER_GELI.
|
||||
|
||||
20180210:
|
||||
The geli password typed at boot is now hidden. To restore the previous
|
||||
behavior, see geli(8) for configuration options.
|
||||
|
@ -123,6 +123,7 @@ __DEFAULT_YES_OPTIONS = \
|
||||
LIB32 \
|
||||
LIBPTHREAD \
|
||||
LIBTHR \
|
||||
LOADER_GELI \
|
||||
LOCALES \
|
||||
LOCATE \
|
||||
LPR \
|
||||
@ -188,6 +189,7 @@ __DEFAULT_NO_OPTIONS = \
|
||||
HESIOD \
|
||||
LIBSOFT \
|
||||
LINT \
|
||||
LOADER_FIREWIRE \
|
||||
LOADER_FORCE_LE \
|
||||
NAND \
|
||||
OFED \
|
||||
|
@ -39,4 +39,19 @@ struct efi_map_header {
|
||||
uint32_t descriptor_version;
|
||||
};
|
||||
|
||||
/*
|
||||
* Placeholder for now
|
||||
*/
|
||||
struct efi_fb {
|
||||
uint64_t fb_addr;
|
||||
uint64_t fb_size;
|
||||
uint32_t fb_height;
|
||||
uint32_t fb_width;
|
||||
uint32_t fb_stride;
|
||||
uint32_t fb_mask_red;
|
||||
uint32_t fb_mask_green;
|
||||
uint32_t fb_mask_blue;
|
||||
uint32_t fb_mask_reserved;
|
||||
};
|
||||
|
||||
#endif /* !_MACHINE_METADATA_H_ */
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#define MODINFOMD_EFI_MAP 0x1001
|
||||
#define MODINFOMD_DTBP 0x1002
|
||||
#define MODINFOMD_EFI_FB 0x1003
|
||||
|
||||
struct efi_map_header {
|
||||
size_t memory_size;
|
||||
@ -38,4 +39,16 @@ struct efi_map_header {
|
||||
uint32_t descriptor_version;
|
||||
};
|
||||
|
||||
struct efi_fb {
|
||||
uint64_t fb_addr;
|
||||
uint64_t fb_size;
|
||||
uint32_t fb_height;
|
||||
uint32_t fb_width;
|
||||
uint32_t fb_stride;
|
||||
uint32_t fb_mask_red;
|
||||
uint32_t fb_mask_green;
|
||||
uint32_t fb_mask_blue;
|
||||
uint32_t fb_mask_reserved;
|
||||
};
|
||||
|
||||
#endif /* !_MACHINE_METADATA_H_ */
|
||||
|
@ -13,10 +13,8 @@ SUBDIR+= man
|
||||
|
||||
.include <bsd.arch.inc.mk>
|
||||
|
||||
# Pick the machine-dependent subdir based on the target architecture.
|
||||
ADIR= ${MACHINE:S/powerpc64/powerpc/}
|
||||
.if exists(${.CURDIR}/${ADIR}/.)
|
||||
SUBDIR+= ${ADIR}
|
||||
.if exists(${.CURDIR}/${MACHINE}/.)
|
||||
SUBDIR+= ${MACHINE}
|
||||
.endif
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
@ -1,16 +1,18 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR+= efi
|
||||
SUBDIR+= libsa32
|
||||
SUBDIR+= zfs
|
||||
SUBDIR+= userboot
|
||||
|
||||
.if !defined(LOADER_NO_GELI_SUPPORT)
|
||||
SUBDIR+= geli
|
||||
.if ${MK_ZFS} != "no"
|
||||
SUBDIR+= zfs zfs32
|
||||
.endif
|
||||
|
||||
.if ${MK_FORTH} != "no"
|
||||
SUBDIR+= ficl32
|
||||
.endif
|
||||
|
||||
SUBDIR+= efi
|
||||
SUBDIR+= userboot
|
||||
|
||||
.if ${LOADER_GELI_SUPPORT:Uyes} == "yes"
|
||||
SUBDIR+= geli
|
||||
.endif
|
||||
|
||||
SUBDIR+= i386
|
||||
|
@ -3,5 +3,8 @@
|
||||
.if ${MK_FDT} != "no"
|
||||
SUBDIR+= fdt
|
||||
.endif
|
||||
.if ${MK_ZFS} != "no"
|
||||
SUBDIR+= zfs
|
||||
.endif
|
||||
|
||||
SUBDIR+= efi uboot
|
||||
|
@ -3,5 +3,8 @@
|
||||
.if ${MK_FDT} != "no"
|
||||
SUBDIR+= fdt
|
||||
.endif
|
||||
.if ${MK_ZFS} != "no"
|
||||
SUBDIR+= zfs
|
||||
.endif
|
||||
|
||||
SUBDIR+= efi
|
||||
|
@ -1,9 +1,10 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR+= efi
|
||||
SUBDIR+= libsa32
|
||||
SUBDIR+= zfs
|
||||
|
||||
.if !defined(LOADER_NO_GELI_SUPPORT)
|
||||
.if ${LOADER_GELI_SUPPORT:Uyes} == "yes"
|
||||
SUBDIR+= geli
|
||||
.endif
|
||||
.if ${MK_ZFS} != "no"
|
||||
SUBDIR+= zfs
|
||||
.endif
|
||||
|
||||
SUBDIR+= efi
|
||||
|
@ -1,16 +1,10 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
.include "defs.mk"
|
||||
|
||||
.if !defined(__BOOT_MAKEFILE_INC__)
|
||||
__BOOT_MAKEFILE_INC__=${MFILE}
|
||||
|
||||
SASRC=${SRCTOP}/sys/boot/libsa
|
||||
# Normal Standalone library
|
||||
LIBSA=${OBJTOP}/sys/boot/libsa/libsa.a
|
||||
# Standalone library compiled for 32-bit version of the processor
|
||||
LIBSA32=${OBJTOP}/sys/boot/libsa32/libsa32.a
|
||||
|
||||
CFLAGS+=-I${SASRC}
|
||||
|
||||
SSP_CFLAGS=
|
||||
|
@ -4,6 +4,5 @@
|
||||
SUBDIR+= fdt
|
||||
.endif
|
||||
|
||||
SUBDIR+= libsa32
|
||||
SUBDIR+= ofw
|
||||
SUBDIR+= uboot
|
||||
|
@ -1,4 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR+= ofw
|
||||
.if ${MK_ZFS} != "no"
|
||||
SUBDIR+= zfs
|
||||
.endif
|
||||
|
@ -1,5 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR= libat91 boot0 boot0iic boot0spi boot2 bootiic bootspi
|
||||
|
||||
.include <bsd.subdir.mk>
|
@ -1,57 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.if !target(__at91_boot_Makefile.inc__)
|
||||
.PATH: ${.CURDIR}/../../../../libkern ${.CURDIR}/../../../../libkern/arm
|
||||
|
||||
__at91_boot_Makefile.inc__:
|
||||
|
||||
# tsc, bwct, kb920x, centipad are the supported flavors
|
||||
BOOT_FLAVOR?=kb920x
|
||||
|
||||
CFLAGS=-Os -mcpu=arm9 -ffreestanding \
|
||||
-I${.CURDIR}/../libat91 \
|
||||
-I${.CURDIR}/../../../.. \
|
||||
-I${.CURDIR}/../../../../arm \
|
||||
-D_KERNEL \
|
||||
-Wall -Waggregate-return \
|
||||
-Wnested-externs \
|
||||
-Wpointer-arith -Wshadow -Wwrite-strings \
|
||||
-Werror \
|
||||
-Wmissing-prototypes \
|
||||
-Wmissing-declarations
|
||||
# -Wstrict-prototypes
|
||||
|
||||
CFLAGS+=-DBOOT_${BOOT_FLAVOR:tu}
|
||||
|
||||
LIBAT91=${.OBJDIR}/../libat91/libat91.a
|
||||
|
||||
LD ?= ld
|
||||
OBJCOPY ?= objcopy
|
||||
|
||||
.if defined(P)
|
||||
${P}: ${P}.out
|
||||
${OBJCOPY} -S -O binary ${P}.out ${.TARGET}
|
||||
@set -- `ls -l ${.TARGET}`; x=$$((12288-$$5)); \
|
||||
echo "$$x bytes available"; test $$x -ge 0
|
||||
|
||||
${P}.out: ${OBJS}
|
||||
${LD} ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LIBAT91}
|
||||
|
||||
CLEANFILES+= ${P} ${P}.out
|
||||
.endif
|
||||
|
||||
.if defined(WITH_TAG_LIST)
|
||||
MK_TAG_LIST:=yes
|
||||
.else
|
||||
MK_TAG_LIST:=no
|
||||
.endif
|
||||
|
||||
.if defined(WITH_FPGA)
|
||||
MK_FPGA:=yes
|
||||
.else
|
||||
MK_FPGA:=no
|
||||
.endif
|
||||
|
||||
.endif
|
||||
|
||||
.include "../Makefile.inc"
|
@ -1,14 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../libat91
|
||||
|
||||
P=boot0
|
||||
FILES=${P}
|
||||
SRCS=arm_init.S main.c
|
||||
MAN=
|
||||
LDFLAGS=-e 0 -T ${.CURDIR}/linker.cfg
|
||||
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
CFLAGS+=-DBOOT_BOOT0
|
@ -1,7 +0,0 @@
|
||||
This is a bootstrap bootloader. It is intended to be used when the
|
||||
AT91RM9200 is running xmodem over DBGU. It will download the next stage
|
||||
of the booting process (or the recovery program) and jump to it. It loads
|
||||
the program at a 1MB offset into SDRAM. Programs are expected to be
|
||||
smaller than this and copy themselves to the right location.
|
||||
|
||||
$FreeBSD$
|
@ -1,84 +0,0 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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)
|
||||
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)
|
||||
}
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
.data :
|
||||
{
|
||||
__data_start = . ;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
_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 = .);
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "at91rm9200.h"
|
||||
#include "lib.h"
|
||||
#include "at91rm9200_lowlevel.h"
|
||||
|
||||
typedef void fn_t(void);
|
||||
|
||||
int main(void);
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
|
||||
fn_t *fn = (fn_t *)(SDRAM_BASE + (1 << 20)); /* Load to base + 1MB */
|
||||
|
||||
while (xmodem_rx(addr) == -1)
|
||||
continue;
|
||||
fn();
|
||||
return (0);
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../libat91
|
||||
|
||||
P=boot0iic
|
||||
FILES=${P}
|
||||
SRCS=arm_init.S main.c
|
||||
MAN=
|
||||
LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
|
||||
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
CFLAGS+=-DBOOT_BOOT0
|
@ -1,52 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "at91rm9200.h"
|
||||
#include "lib.h"
|
||||
#include "at91rm9200_lowlevel.h"
|
||||
|
||||
int main(void);
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
|
||||
int len, sec;
|
||||
|
||||
printf("\nSend data to be written into EEPROM\n");
|
||||
while ((len = xmodem_rx(addr)) == -1)
|
||||
continue;
|
||||
sec = GetSeconds() + 1;
|
||||
while (sec >= GetSeconds())
|
||||
continue;
|
||||
printf("\nWriting EEPROM from 0x%x to addr 0, 0x%x bytes\n", addr,
|
||||
len);
|
||||
InitEEPROM();
|
||||
printf("init done\n");
|
||||
WriteEEPROM(0, addr, len);
|
||||
printf("\nWrote %d bytes. Press reset\n", len);
|
||||
return (1);
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../libat91
|
||||
|
||||
P=boot0spi
|
||||
FILES=${P}
|
||||
SRCS=arm_init.S main.c
|
||||
MAN=
|
||||
LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
|
||||
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
CFLAGS+=-DBOOT_BOOT0
|
@ -1,65 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "at91rm9200.h"
|
||||
#include "lib.h"
|
||||
#include "at91rm9200_lowlevel.h"
|
||||
#include "spi_flash.h"
|
||||
|
||||
#define OFFSET 0
|
||||
|
||||
int main(void);
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int len, i, j, off, sec;
|
||||
char *addr = (char *)SDRAM_BASE + (1 << 20); /* download at + 1MB */
|
||||
char *addr2 = (char *)SDRAM_BASE + (2 << 20); /* readback to + 2MB */
|
||||
|
||||
SPI_InitFlash();
|
||||
printf("Waiting for data\n");
|
||||
while ((len = xmodem_rx(addr)) == -1)
|
||||
continue;
|
||||
printf("Writing %u bytes at %u\n", len, OFFSET);
|
||||
for (i = 0; i < len; i+= FLASH_PAGE_SIZE) {
|
||||
off = i + OFFSET;
|
||||
for (j = 0; j < 10; j++) {
|
||||
SPI_WriteFlash(off, addr + i, FLASH_PAGE_SIZE);
|
||||
SPI_ReadFlash(off, addr2 + i, FLASH_PAGE_SIZE);
|
||||
if (p_memcmp(addr + i, addr2 + i, FLASH_PAGE_SIZE) == 0)
|
||||
break;
|
||||
}
|
||||
if (j >= 10)
|
||||
printf("Bad Readback at %u\n", i);
|
||||
}
|
||||
sec = GetSeconds() + 2;
|
||||
while (sec <= GetSeconds())
|
||||
continue;
|
||||
printf("Done\n");
|
||||
reset();
|
||||
return (1);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../libat91 ${.CURDIR}/../bootspi
|
||||
|
||||
P=boot2
|
||||
FILES=${P}
|
||||
SRCS=arm_init.S boot2.c ${BOOT_FLAVOR:tl}_board.c
|
||||
MAN=
|
||||
LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
|
||||
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
.if ${BOOT_FLAVOR} == "kb920x"
|
||||
CFLAGS+=-DBOOT_IIC
|
||||
.endif
|
||||
CFLAGS+= \
|
||||
-I${.CURDIR}/../bootspi \
|
||||
-I${.CURDIR}/../../../common \
|
||||
-I${.CURDIR}/../../../.. \
|
||||
-D_KERNEL \
|
||||
-DUFS1_ONLY
|
@ -1,29 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
void Update(void);
|
||||
void board_init(void);
|
||||
int drvread(void *, unsigned, unsigned);
|
@ -1,361 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 John Hay
|
||||
* Copyright (c) 2006 M Warner Losh <imp@freebsd.org>
|
||||
* Copyright (c) 1998 Robert Nordier
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/diskmbr.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/reboot.h>
|
||||
|
||||
#include <machine/elf.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "board.h"
|
||||
#include "paths.h"
|
||||
#include "rbx.h"
|
||||
|
||||
#undef PATH_KERNEL
|
||||
#define PATH_KERNEL "/boot/kernel/kernel.gz.tramp"
|
||||
|
||||
extern uint32_t _end;
|
||||
|
||||
#define NOPT 6
|
||||
|
||||
static const char optstr[NOPT] = "agnrsv";
|
||||
static const unsigned char bootflags[NOPT] = {
|
||||
RBX_ASKNAME,
|
||||
RBX_GDB,
|
||||
RBX_NOINTR,
|
||||
RBX_DFLTROOT,
|
||||
RBX_SINGLE,
|
||||
RBX_VERBOSE
|
||||
};
|
||||
|
||||
unsigned board_id; /* board type to pass to kernel, if set by board_* code */
|
||||
unsigned dsk_start;
|
||||
static char cmd[512];
|
||||
static char kname[1024];
|
||||
static uint32_t opts;
|
||||
static uint8_t dsk_meta;
|
||||
|
||||
int main(void);
|
||||
static void load(void);
|
||||
static int parse(void);
|
||||
static int dskread(void *, unsigned, unsigned);
|
||||
#ifdef FIXUP_BOOT_DRV
|
||||
static void fixup_boot_drv(caddr_t, int, int, int);
|
||||
#endif
|
||||
|
||||
#define UFS_SMALL_CGBASE
|
||||
#include "ufsread.c"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
|
||||
{
|
||||
if ((size_t)fsread(inode, buf, nbyte) != nbyte)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
getstr(int c)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = cmd;
|
||||
if (c == 0)
|
||||
c = getc(10000);
|
||||
for (;;) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
break;
|
||||
case '\177':
|
||||
case '\b':
|
||||
if (s > cmd) {
|
||||
s--;
|
||||
printf("\b \b");
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
*s = 0;
|
||||
return;
|
||||
default:
|
||||
if (s - cmd < sizeof(cmd) - 1)
|
||||
*s++ = c;
|
||||
xputchar(c);
|
||||
}
|
||||
c = getc(10000);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int autoboot, c = 0;
|
||||
ufs_ino_t ino;
|
||||
|
||||
dmadat = (void *)(0x20000000 + (16 << 20));
|
||||
board_init();
|
||||
|
||||
autoboot = 1;
|
||||
|
||||
/* Process configuration file */
|
||||
if ((ino = lookup(PATH_CONFIG)) ||
|
||||
(ino = lookup(PATH_DOTCONFIG)))
|
||||
fsread(ino, cmd, sizeof(cmd));
|
||||
|
||||
if (*cmd) {
|
||||
if (parse())
|
||||
autoboot = 0;
|
||||
printf("%s: %s\n", PATH_CONFIG, cmd);
|
||||
/* Do not process this command twice */
|
||||
*cmd = 0;
|
||||
}
|
||||
|
||||
if (*kname == '\0')
|
||||
strcpy(kname, PATH_KERNEL);
|
||||
|
||||
/* Present the user with the boot2 prompt. */
|
||||
for (;;) {
|
||||
printf("\nDefault: %s\nboot: ", kname);
|
||||
if (!autoboot ||
|
||||
(OPT_CHECK(RBX_NOINTR) == 0 && (c = getc(2)) != 0))
|
||||
getstr(c);
|
||||
xputchar('\n');
|
||||
autoboot = 0;
|
||||
c = 0;
|
||||
if (parse())
|
||||
xputchar('\a');
|
||||
else
|
||||
load();
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
load(void)
|
||||
{
|
||||
Elf32_Ehdr eh;
|
||||
static Elf32_Phdr ep[2];
|
||||
caddr_t p;
|
||||
ufs_ino_t ino;
|
||||
uint32_t addr;
|
||||
int i, j;
|
||||
#ifdef FIXUP_BOOT_DRV
|
||||
caddr_t staddr;
|
||||
int klen;
|
||||
|
||||
staddr = (caddr_t)0xffffffff;
|
||||
klen = 0;
|
||||
#endif
|
||||
if (!(ino = lookup(kname))) {
|
||||
if (!ls)
|
||||
printf("No %s\n", kname);
|
||||
return;
|
||||
}
|
||||
if (xfsread(ino, &eh, sizeof(eh)))
|
||||
return;
|
||||
if (!IS_ELF(eh)) {
|
||||
printf("Invalid %s\n", "format");
|
||||
return;
|
||||
}
|
||||
fs_off = eh.e_phoff;
|
||||
for (j = i = 0; i < eh.e_phnum && j < 2; i++) {
|
||||
if (xfsread(ino, ep + j, sizeof(ep[0])))
|
||||
return;
|
||||
if (ep[j].p_type == PT_LOAD)
|
||||
j++;
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
p = (caddr_t)ep[i].p_paddr;
|
||||
fs_off = ep[i].p_offset;
|
||||
#ifdef FIXUP_BOOT_DRV
|
||||
if (staddr == (caddr_t)0xffffffff)
|
||||
staddr = p;
|
||||
klen += ep[i].p_filesz;
|
||||
#endif
|
||||
if (xfsread(ino, p, ep[i].p_filesz))
|
||||
return;
|
||||
}
|
||||
addr = eh.e_entry;
|
||||
#ifdef FIXUP_BOOT_DRV
|
||||
fixup_boot_drv(staddr, klen, bootslice, bootpart);
|
||||
#endif
|
||||
((void(*)(int, int, int, int))addr)(opts & RBX_MASK, board_id, 0, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
parse()
|
||||
{
|
||||
char *arg = cmd;
|
||||
char *ep, *p;
|
||||
int c, i;
|
||||
|
||||
while ((c = *arg++)) {
|
||||
if (c == ' ' || c == '\t' || c == '\n')
|
||||
continue;
|
||||
for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
|
||||
ep = p;
|
||||
if (*p)
|
||||
*p++ = 0;
|
||||
if (c == '-') {
|
||||
while ((c = *arg++)) {
|
||||
for (i = 0; c != optstr[i]; i++)
|
||||
if (i == NOPT - 1)
|
||||
return -1;
|
||||
opts ^= OPT_SET(bootflags[i]);
|
||||
}
|
||||
} else {
|
||||
arg--;
|
||||
if ((i = ep - arg)) {
|
||||
if ((size_t)i >= sizeof(kname))
|
||||
return -1;
|
||||
memcpy(kname, arg, i + 1);
|
||||
}
|
||||
}
|
||||
arg = p;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dskread(void *buf, unsigned lba, unsigned nblk)
|
||||
{
|
||||
struct dos_partition *dp;
|
||||
struct disklabel *d;
|
||||
char *sec;
|
||||
int i;
|
||||
|
||||
if (!dsk_meta) {
|
||||
sec = dmadat->secbuf;
|
||||
dsk_start = 0;
|
||||
if (drvread(sec, DOSBBSECTOR, 1))
|
||||
return -1;
|
||||
dp = (void *)(sec + DOSPARTOFF);
|
||||
for (i = 0; i < NDOSPART; i++) {
|
||||
if (dp[i].dp_typ == DOSPTYP_386BSD)
|
||||
break;
|
||||
}
|
||||
if (i == NDOSPART)
|
||||
return -1;
|
||||
/*
|
||||
* Although dp_start is aligned within the disk
|
||||
* partition structure, DOSPARTOFF is 446, which is
|
||||
* only word (2) aligned, not longword (4) aligned.
|
||||
* Cope by using memcpy to fetch the start of this
|
||||
* partition.
|
||||
*/
|
||||
memcpy(&dsk_start, &dp[1].dp_start, 4);
|
||||
if (drvread(sec, dsk_start + LABELSECTOR, 1))
|
||||
return -1;
|
||||
d = (void *)(sec + LABELOFFSET);
|
||||
if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) {
|
||||
printf("Invalid %s\n", "label");
|
||||
return -1;
|
||||
}
|
||||
if (!d->d_partitions[0].p_size) {
|
||||
printf("Invalid %s\n", "partition");
|
||||
return -1;
|
||||
}
|
||||
dsk_start += d->d_partitions[0].p_offset;
|
||||
dsk_start -= d->d_partitions[RAW_PART].p_offset;
|
||||
dsk_meta++;
|
||||
}
|
||||
return drvread(buf, dsk_start + lba, nblk);
|
||||
}
|
||||
|
||||
#ifdef FIXUP_BOOT_DRV
|
||||
/*
|
||||
* fixup_boot_drv() will try to find the ROOTDEVNAME spec in the kernel
|
||||
* and change it to what was specified on the comandline or /boot.conf
|
||||
* file or to what was encountered on the disk. It will try to handle 3
|
||||
* different disk layouts, raw (dangerously dedicated), slice only and
|
||||
* slice + partition. It will look for the following strings in the
|
||||
* kernel, but if it is one of the first three, the string in the kernel
|
||||
* must use the correct form to match the actual disk layout:
|
||||
* - ufs:ad0a
|
||||
* - ufs:ad0s1
|
||||
* - ufs:ad0s1a
|
||||
* - ufs:ROOTDEVNAME
|
||||
* In the case of the first three strings, only the "a" at the end and
|
||||
* the "1" after the "s" will be modified, if they exist. The string
|
||||
* length will not be changed. In the case of the last string, the
|
||||
* whole string will be built up and nul, '\0' terminated.
|
||||
*/
|
||||
static void
|
||||
fixup_boot_drv(caddr_t addr, int klen, int bs, int bp)
|
||||
{
|
||||
const u_int8_t op[] = "ufs:ROOTDEVNAME";
|
||||
const u_int8_t op2[] = "ufs:ad0";
|
||||
u_int8_t *p, *ps;
|
||||
|
||||
DPRINTF("fixup_boot_drv: 0x%x, %d, slice %d, partition %d\n",
|
||||
(int)addr, klen, bs, bp);
|
||||
if (bs > 4)
|
||||
return;
|
||||
if (bp > 7)
|
||||
return;
|
||||
ps = memmem(addr, klen, op, sizeof(op));
|
||||
if (ps != NULL) {
|
||||
p = ps + 4; /* past ufs: */
|
||||
DPRINTF("Found it at 0x%x\n", (int)ps);
|
||||
p[0] = 'a'; p[1] = 'd'; p[2] = '0'; /* ad0 */
|
||||
p += 3;
|
||||
if (bs > 0) {
|
||||
/* append slice */
|
||||
*p++ = 's';
|
||||
*p++ = bs + '0';
|
||||
}
|
||||
if (disk_layout != DL_SLICE) {
|
||||
/* append partition */
|
||||
*p++ = bp + 'a';
|
||||
}
|
||||
*p = '\0';
|
||||
} else {
|
||||
ps = memmem(addr, klen, op2, sizeof(op2) - 1);
|
||||
if (ps != NULL) {
|
||||
p = ps + sizeof(op2) - 1;
|
||||
DPRINTF("Found it at 0x%x\n", (int)ps);
|
||||
if (*p == 's') {
|
||||
/* fix slice */
|
||||
p++;
|
||||
*p++ = bs + '0';
|
||||
}
|
||||
if (*p == 'a')
|
||||
*p = bp + 'a';
|
||||
}
|
||||
}
|
||||
if (ps == NULL) {
|
||||
printf("Could not locate \"%s\" to fix kernel boot device, "
|
||||
"check ROOTDEVNAME is set\n", op);
|
||||
return;
|
||||
}
|
||||
DPRINTF("Changed boot device to %s\n", ps);
|
||||
}
|
||||
#endif
|
@ -1,125 +0,0 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "at91rm9200_lowlevel.h"
|
||||
#include "at91rm9200.h"
|
||||
#include "emac.h"
|
||||
#include "lib.h"
|
||||
#include "ee.h"
|
||||
#include "board.h"
|
||||
#include "sd-card.h"
|
||||
|
||||
unsigned char mac[6] = { 0x00, 0x0e, 0x42, 0x02, 0x00, 0x28 };
|
||||
|
||||
static void USART0_Init();
|
||||
static void USART1_Init();
|
||||
static void USART2_Init();
|
||||
static void USART3_Init();
|
||||
static void DS1672_Init();
|
||||
|
||||
static void
|
||||
DS1672_Init() {
|
||||
char buf[] = {0x00, 0xa9};
|
||||
|
||||
EEWrite(0xd0, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static void
|
||||
USART0_Init() {
|
||||
|
||||
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
|
||||
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
|
||||
|
||||
// setup GPIO
|
||||
pPio->PIO_ASR = AT91C_PA17_TXD0 | AT91C_PA18_RXD0;
|
||||
pPio->PIO_PDR = AT91C_PA17_TXD0 | AT91C_PA18_RXD0;
|
||||
|
||||
// enable power
|
||||
pPMC->PMC_PCER = 1u << AT91C_ID_US0;
|
||||
}
|
||||
|
||||
static void
|
||||
USART1_Init() {
|
||||
|
||||
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
|
||||
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
|
||||
|
||||
// setup GPIO
|
||||
pPio->PIO_ASR = AT91C_PB20_TXD1 | AT91C_PB21_RXD1;
|
||||
pPio->PIO_PDR = AT91C_PB20_TXD1 | AT91C_PB21_RXD1;
|
||||
|
||||
// enable power
|
||||
pPMC->PMC_PCER = 1u << AT91C_ID_US1;
|
||||
}
|
||||
|
||||
static void
|
||||
USART2_Init() {
|
||||
|
||||
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
|
||||
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
|
||||
|
||||
// setup GPIO
|
||||
pPio->PIO_ASR = AT91C_PA23_TXD2 | AT91C_PA22_RXD2;
|
||||
pPio->PIO_PDR = AT91C_PA23_TXD2 | AT91C_PA22_RXD2;
|
||||
|
||||
// enable power
|
||||
pPMC->PMC_PCER = 1u << AT91C_ID_US2;
|
||||
}
|
||||
|
||||
static void
|
||||
USART3_Init() {
|
||||
|
||||
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
|
||||
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
|
||||
|
||||
// setup GPIO
|
||||
pPio->PIO_BSR = AT91C_PA5_TXD3 | AT91C_PA6_RXD3;
|
||||
pPio->PIO_PDR = AT91C_PA5_TXD3 | AT91C_PA6_RXD3;
|
||||
|
||||
// enable power
|
||||
pPMC->PMC_PCER = 1u << AT91C_ID_US3;
|
||||
}
|
||||
|
||||
void
|
||||
board_init(void)
|
||||
{
|
||||
|
||||
printf("\n\n");
|
||||
printf("BWCT FSB-A920-1\n");
|
||||
printf("http://www.bwct.de\n");
|
||||
printf("\n");
|
||||
#if defined(SDRAM_128M)
|
||||
printf("AT92RM9200 180MHz 128MB\n");
|
||||
#else
|
||||
printf("AT92RM9200 180MHz 64MB\n");
|
||||
#endif
|
||||
printf("Initialising USART0\n");
|
||||
USART0_Init();
|
||||
printf("Initialising USART1\n");
|
||||
USART1_Init();
|
||||
printf("Initialising USART2\n");
|
||||
USART2_Init();
|
||||
printf("Initialising USART3\n");
|
||||
USART3_Init();
|
||||
printf("Initialising TWI\n");
|
||||
EEInit();
|
||||
printf("Initialising DS1672\n");
|
||||
DS1672_Init();
|
||||
printf("Initialising Ethernet\n");
|
||||
printf("MAC %x:%x:%x:%x:%x:%x\n", mac[0],
|
||||
mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
EMAC_Init();
|
||||
EMAC_SetMACAddress(mac);
|
||||
printf("Initialising SD-card\n");
|
||||
sdcard_init();
|
||||
}
|
||||
|
||||
#include "../bootspi/ee.c"
|
||||
|
||||
int
|
||||
drvread(void *buf, unsigned lba, unsigned nblk)
|
||||
{
|
||||
return (MCI_read((char *)buf, lba << 9, nblk << 9));
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "emac.h"
|
||||
#include "lib.h"
|
||||
#include "board.h"
|
||||
#include "sd-card.h"
|
||||
|
||||
unsigned char mac[6] = { 0x42, 0x53, 0x44, 0, 1, 1 };
|
||||
|
||||
static void
|
||||
MacFromEE()
|
||||
{
|
||||
#if 0
|
||||
uint32_t sig;
|
||||
sig = 0;
|
||||
ReadEEPROM(12 * 1024, (uint8_t *)&sig, sizeof(sig));
|
||||
if (sig != 0x92021054)
|
||||
return;
|
||||
ReadEEPROM(12 * 1024 + 4, mac, 6);
|
||||
#endif
|
||||
printf("MAC %x:%x:%x:%x:%x:%x\n", mac[0],
|
||||
mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
}
|
||||
|
||||
void
|
||||
board_init(void)
|
||||
{
|
||||
InitEEPROM();
|
||||
MacFromEE();
|
||||
EMAC_Init();
|
||||
EMAC_SetMACAddress(mac);
|
||||
while (sdcard_init() == 0)
|
||||
printf("Looking for SD card\n");
|
||||
}
|
||||
|
||||
int
|
||||
drvread(void *buf, unsigned lba, unsigned nblk)
|
||||
{
|
||||
return (MCI_read((char *)buf, lba << 9, nblk << 9));
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "emac.h"
|
||||
#include "lib.h"
|
||||
#include "board.h"
|
||||
#include "sd-card.h"
|
||||
|
||||
unsigned char mac[6] = { 0x42, 0x53, 0x44, 0, 0, 1 };
|
||||
|
||||
static void
|
||||
MacFromEE()
|
||||
{
|
||||
uint32_t sig;
|
||||
sig = 0;
|
||||
ReadEEPROM(12 * 1024, (uint8_t *)&sig, sizeof(sig));
|
||||
if (sig != 0x92021054)
|
||||
return;
|
||||
ReadEEPROM(12 * 1024 + 4, mac, 6);
|
||||
printf("MAC %x:%x:%x:%x:%x:%x\n", mac[0],
|
||||
mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
}
|
||||
|
||||
void
|
||||
board_init(void)
|
||||
{
|
||||
InitEEPROM();
|
||||
MacFromEE();
|
||||
EMAC_Init();
|
||||
EMAC_SetMACAddress(mac);
|
||||
while (sdcard_init() == 0)
|
||||
printf("Looking for SD card\n");
|
||||
}
|
||||
|
||||
int
|
||||
drvread(void *buf, unsigned lba, unsigned nblk)
|
||||
{
|
||||
return (MCI_read((char *)buf, lba << 9, nblk << 9));
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../libat91
|
||||
|
||||
P=bootiic
|
||||
FILES=${P}
|
||||
SRCS=arm_init.S main.c loader_prompt.c env_vars.c
|
||||
MAN=
|
||||
LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
|
||||
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
CFLAGS += -DBOOT_IIC -DBOOT_COMMANDS
|
@ -1,35 +0,0 @@
|
||||
$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
|
||||
|
@ -1,207 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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 "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 environment 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;
|
||||
ch = '\r';
|
||||
}
|
||||
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;
|
||||
}
|
||||
memcpy(cPtr, boot_commands[i], copySize);
|
||||
cPtr += copySize;
|
||||
*cPtr++ = 0;
|
||||
}
|
||||
|
||||
/* We're executing in low RAM so addr in ram == offset in eeprom */
|
||||
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);
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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_ */
|
@ -1,387 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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"
|
||||
#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 const char *backspaceString = "\010 \010";
|
||||
|
||||
static const 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 (!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, i;
|
||||
|
||||
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]);
|
||||
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:\n"
|
||||
"\tc\n"
|
||||
"\td\n"
|
||||
"\te\n"
|
||||
"\tip\n"
|
||||
"\tserver_ip\n"
|
||||
"\tm\n"
|
||||
"\ttftp\n"
|
||||
"\ts\n"
|
||||
#ifdef SUPPORT_TAG_LIST
|
||||
"\tt\n"
|
||||
#endif
|
||||
"\tw\n"
|
||||
"\tx\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 char mac[6];
|
||||
|
||||
if (argc > 6) {
|
||||
for (i = 0; i < 6; i++)
|
||||
mac[i] = p_ASCIIToHex(argv[i + 1]);
|
||||
EMAC_SetMACAddress(mac);
|
||||
}
|
||||
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
|
||||
if (argc > 1)
|
||||
xmodem_rx((char *)p_ASCIIToHex(argv[1]));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\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 ''.
|
||||
* .KB_C_FN_DEFINITION_END
|
||||
*/
|
||||
static void
|
||||
ServicePrompt(char p_char)
|
||||
{
|
||||
if (p_char == '\r')
|
||||
p_char = 0;
|
||||
|
||||
if (p_char == '\010') {
|
||||
if (buffCount) {
|
||||
/* handle backspace BS */
|
||||
inputBuffer[--buffCount] = 0;
|
||||
printf(backspaceString);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (buffCount < MAX_INPUT_SIZE - 1) {
|
||||
inputBuffer[buffCount++] = p_char;
|
||||
putchar(p_char);
|
||||
}
|
||||
if (!p_char) {
|
||||
printf("\n");
|
||||
ParseCommand(inputBuffer);
|
||||
p_memset(inputBuffer, 0, MAX_INPUT_SIZE);
|
||||
buffCount = 0;
|
||||
printf("\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("\n>");
|
||||
|
||||
while (1)
|
||||
if ((ch = ((*inputFunction)(0))) > 0)
|
||||
ServicePrompt(ch);
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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_ */
|
@ -1,55 +0,0 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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"
|
||||
|
||||
int main(void);
|
||||
|
||||
/*
|
||||
* .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)
|
||||
{
|
||||
InitEEPROM();
|
||||
EMAC_Init();
|
||||
LoadBootCommands();
|
||||
printf("\n\rKB9202(www.kwikbyte.com)\n\rAuto boot..\n\r");
|
||||
if (getc(1) == -1)
|
||||
ExecuteEnvironmentFunctions();
|
||||
Bootloader(0);
|
||||
|
||||
return (1);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
||||
.PATH: ${.CURDIR}/../libat91
|
||||
|
||||
P=bootspi
|
||||
FILES=${P}
|
||||
SRCS=arm_init.S main.c loader_prompt.c env_vars.c ee.c
|
||||
MAN=
|
||||
LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
|
||||
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
.if ${MK_FPGA} == "yes"
|
||||
CFLAGS += -DTSC_FPGA
|
||||
.endif
|
||||
CFLAGS += -DBOOT_COMMANDS
|
@ -1,34 +0,0 @@
|
||||
$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
|
@ -1,160 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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"
|
||||
#include "ee.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 0x40
|
||||
|
||||
#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
|
||||
EEInit(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_PIO_PA25 | AT91C_PIO_PA26;
|
||||
pPio->PIO_PDR = AT91C_PIO_PA25 | AT91C_PIO_PA26;
|
||||
|
||||
pPio->PIO_MDDR = ~AT91C_PIO_PA25;
|
||||
pPio->PIO_MDER = AT91C_PIO_PA25;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
iicaddr(unsigned ee_off)
|
||||
{
|
||||
return (TWSI_EEPROM_ADDRESS | ((ee_off >> 8) & 0x7));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .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
|
||||
EERead(unsigned ee_off, char *data_addr, unsigned size)
|
||||
{
|
||||
const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
|
||||
unsigned int status;
|
||||
|
||||
if ((ee_off & ~0xff) != ((ee_off + size) & ~0xff)) {
|
||||
printf("Crosses page boundary: 0x%x 0x%x\n", ee_off, size);
|
||||
return;
|
||||
}
|
||||
|
||||
status = twiPtr->TWI_SR;
|
||||
status = twiPtr->TWI_RHR;
|
||||
twiPtr->TWI_MMR = (iicaddr(ee_off) << 16) | AT91C_TWI_IADRSZ_1_BYTE |
|
||||
AT91C_TWI_MREAD;
|
||||
twiPtr->TWI_IADR = ee_off & 0xff;
|
||||
twiPtr->TWI_CR = AT91C_TWI_START;
|
||||
while (size-- > 1) {
|
||||
while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY))
|
||||
continue;
|
||||
*(data_addr++) = twiPtr->TWI_RHR;
|
||||
}
|
||||
twiPtr->TWI_CR = AT91C_TWI_STOP;
|
||||
status = twiPtr->TWI_SR;
|
||||
while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
|
||||
continue;
|
||||
*data_addr = twiPtr->TWI_RHR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .KB_C_FN_DEFINITION_START
|
||||
* void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size)
|
||||
* This global function writes data to the eeprom at ee_off 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
|
||||
EEWrite(unsigned ee_off, const char *data_addr, unsigned size)
|
||||
{
|
||||
const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
|
||||
unsigned status;
|
||||
char test_data;
|
||||
|
||||
while (size--) {
|
||||
// Set the TWI Master Mode Register
|
||||
twiPtr->TWI_MMR = (iicaddr(ee_off) << 16) |
|
||||
AT91C_TWI_IADRSZ_1_BYTE;
|
||||
twiPtr->TWI_IADR = ee_off++;
|
||||
status = twiPtr->TWI_SR;
|
||||
|
||||
// Load one data byte
|
||||
twiPtr->TWI_THR = *(data_addr++);
|
||||
twiPtr->TWI_CR = AT91C_TWI_START;
|
||||
while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY))
|
||||
continue;
|
||||
twiPtr->TWI_CR = AT91C_TWI_STOP;
|
||||
status = twiPtr->TWI_SR;
|
||||
while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
|
||||
continue;
|
||||
|
||||
// wait for write operation to complete, it is done once
|
||||
// we can read it back...
|
||||
EERead(ee_off, &test_data, 1);
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
/* $FreeBSD$ */
|
||||
|
||||
void EEInit(void);
|
||||
void EERead(unsigned ee_off, char *data_addr, unsigned size);
|
||||
void EEWrite(unsigned ee_off, const char *data_addr, unsigned size);
|
||||
|
@ -1,130 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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 "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 environment 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;
|
||||
ch = '\r';
|
||||
}
|
||||
return (ch);
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
/*************************** GLOBAL FUNCTIONS ********************************/
|
||||
|
||||
|
||||
/*
|
||||
* .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;
|
||||
|
||||
for (i = 0; boot_commands[i][0]; i++)
|
||||
printf("0x%x : %s[E]\n", i, boot_commands[i]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .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;
|
||||
char *cptr;
|
||||
|
||||
p_memset((char*)boot_commands, 0, sizeof(boot_commands));
|
||||
cptr = &BootCommandSection;
|
||||
for (index = 0; *cptr; index++) {
|
||||
for (j = 0; *cptr; j++)
|
||||
boot_commands[index][j] = *cptr++;
|
||||
cptr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .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();
|
||||
printf("Autoboot...\n");
|
||||
Bootloader(ReadCharFromEnvironment);
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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_ */
|
@ -1,363 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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 "at91rm9200.h"
|
||||
#include "emac.h"
|
||||
#include "loader_prompt.h"
|
||||
#include "env_vars.h"
|
||||
#include "lib.h"
|
||||
#include "spi_flash.h"
|
||||
#include "ee.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];
|
||||
|
||||
#define FLASH_OFFSET (0 * FLASH_PAGE_SIZE)
|
||||
#define KERNEL_OFFSET (220 * FLASH_PAGE_SIZE)
|
||||
#define KERNEL_LEN (6 * 1024 * FLASH_PAGE_SIZE)
|
||||
static const char *backspaceString = "\010 \010";
|
||||
|
||||
static const command_entry_t CommandTable[] = {
|
||||
{COMMAND_DUMP, "d"},
|
||||
{COMMAND_EXEC, "e"},
|
||||
{COMMAND_LOCAL_IP, "ip"},
|
||||
{COMMAND_MAC, "m"},
|
||||
{COMMAND_SERVER_IP, "server_ip"},
|
||||
{COMMAND_TFTP, "tftp"},
|
||||
{COMMAND_XMODEM, "x"},
|
||||
{COMMAND_RESET, "R"},
|
||||
{COMMAND_LOAD_SPI_KERNEL, "k"},
|
||||
{COMMAND_REPLACE_KERNEL_VIA_XMODEM, "K"},
|
||||
{COMMAND_REPLACE_FLASH_VIA_XMODEM, "I"},
|
||||
{COMMAND_REPLACE_ID_EEPROM, "E"},
|
||||
{COMMAND_FINAL_FLAG, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* .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 (!strcmp(CommandTable[i].c_string, cPtr))
|
||||
return (CommandTable[i].command);
|
||||
|
||||
return (COMMAND_INVALID);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .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);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
UpdateEEProm(int eeaddr)
|
||||
{
|
||||
char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
|
||||
int len;
|
||||
|
||||
while ((len = xmodem_rx(addr)) == -1)
|
||||
continue;
|
||||
printf("\nDownloaded %u bytes.\n", len);
|
||||
WriteEEPROM(eeaddr, 0, addr, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
UpdateFlash(int offset)
|
||||
{
|
||||
char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
|
||||
int len, i, off;
|
||||
|
||||
while ((len = xmodem_rx(addr)) == -1)
|
||||
continue;
|
||||
printf("\nDownloaded %u bytes.\n", len);
|
||||
for (i = 0; i < len; i+= FLASH_PAGE_SIZE) {
|
||||
off = i + offset;
|
||||
SPI_WriteFlash(off, addr + i, FLASH_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
LoadKernelFromSpi(char *addr)
|
||||
{
|
||||
int i, off;
|
||||
|
||||
for (i = 0; i < KERNEL_LEN; i+= FLASH_PAGE_SIZE) {
|
||||
off = i + KERNEL_OFFSET;
|
||||
SPI_ReadFlash(off, addr + i, FLASH_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* .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, i;
|
||||
|
||||
if ((argc = BreakCommand(buffer)) < 1)
|
||||
return;
|
||||
|
||||
switch (StringToCommand(argv[0])) {
|
||||
case COMMAND_DUMP:
|
||||
// display boot commands
|
||||
DumpBootCommands();
|
||||
break;
|
||||
|
||||
case COMMAND_EXEC:
|
||||
{
|
||||
// "e <address>"
|
||||
// execute at address
|
||||
void (*execAddr)(unsigned, unsigned);
|
||||
|
||||
if (argc > 1) {
|
||||
/* in future, include machtypes (MACH_KB9200 = 612) */
|
||||
execAddr = (void (*)(unsigned, unsigned))
|
||||
p_ASCIIToHex(argv[1]);
|
||||
(*execAddr)(0, 612);
|
||||
}
|
||||
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_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 char mac[6];
|
||||
|
||||
if (argc > 6) {
|
||||
for (i = 0; i < 6; i++)
|
||||
mac[i] = p_ASCIIToHex(argv[i + 1]);
|
||||
EMAC_SetMACAddress(mac);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case COMMAND_LOAD_SPI_KERNEL:
|
||||
// "k <address>"
|
||||
if (argc > 1)
|
||||
LoadKernelFromSpi((char *)p_ASCIIToHex(argv[1]));
|
||||
break;
|
||||
|
||||
case COMMAND_XMODEM:
|
||||
// "x <address>"
|
||||
// download X-modem record at address
|
||||
if (argc > 1)
|
||||
xmodem_rx((char *)p_ASCIIToHex(argv[1]));
|
||||
break;
|
||||
|
||||
case COMMAND_RESET:
|
||||
printf("Reset\n");
|
||||
reset();
|
||||
while (1) continue;
|
||||
break;
|
||||
|
||||
case COMMAND_REPLACE_KERNEL_VIA_XMODEM:
|
||||
printf("Updating KERNEL image\n");
|
||||
UpdateFlash(KERNEL_OFFSET);
|
||||
break;
|
||||
case COMMAND_REPLACE_FLASH_VIA_XMODEM:
|
||||
printf("Updating FLASH image\n");
|
||||
UpdateFlash(FLASH_OFFSET);
|
||||
break;
|
||||
|
||||
case COMMAND_REPLACE_ID_EEPROM:
|
||||
{
|
||||
char buf[25];
|
||||
printf("Testing Config EEPROM\n");
|
||||
EEWrite(0, "This is a test", 15);
|
||||
EERead(0, buf, 15);
|
||||
printf("Found '%s'\n", buf);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\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 ''.
|
||||
* .KB_C_FN_DEFINITION_END
|
||||
*/
|
||||
static void
|
||||
ServicePrompt(char p_char)
|
||||
{
|
||||
if (p_char == '\r')
|
||||
p_char = 0;
|
||||
|
||||
if (p_char == '\010') {
|
||||
if (buffCount) {
|
||||
/* handle backspace BS */
|
||||
inputBuffer[--buffCount] = 0;
|
||||
printf(backspaceString);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (buffCount < MAX_INPUT_SIZE - 1) {
|
||||
inputBuffer[buffCount++] = p_char;
|
||||
putchar(p_char);
|
||||
}
|
||||
if (!p_char) {
|
||||
printf("\n");
|
||||
ParseCommand(inputBuffer);
|
||||
p_memset(inputBuffer, 0, MAX_INPUT_SIZE);
|
||||
buffCount = 0;
|
||||
printf("\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;
|
||||
|
||||
printf("\n>");
|
||||
|
||||
while (1)
|
||||
if ((ch = ((*inputFunction)(0))) > 0)
|
||||
ServicePrompt(ch);
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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_RESET,
|
||||
COMMAND_LOAD_SPI_KERNEL,
|
||||
COMMAND_REPLACE_KERNEL_VIA_XMODEM,
|
||||
COMMAND_REPLACE_FLASH_VIA_XMODEM,
|
||||
COMMAND_REPLACE_FPGA_VIA_XMODEM,
|
||||
COMMAND_REPLACE_ID_EEPROM,
|
||||
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));
|
||||
void fpga_load(void);
|
||||
|
||||
#endif /* _LOADER_PROMPT_H_ */
|
@ -1,65 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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$
|
||||
*/
|
||||
|
||||
#include "env_vars.h"
|
||||
#include "at91rm9200.h"
|
||||
#include "at91rm9200_lowlevel.h"
|
||||
#include "loader_prompt.h"
|
||||
#include "emac.h"
|
||||
#include "lib.h"
|
||||
#include "spi_flash.h"
|
||||
#include "ee.h"
|
||||
|
||||
int main(void);
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
printf("\nBoot\n");
|
||||
EEInit();
|
||||
SPI_InitFlash();
|
||||
#ifdef TSC_FPGA
|
||||
fpga_load();
|
||||
#endif
|
||||
EMAC_Init();
|
||||
LoadBootCommands();
|
||||
if (getc(1) == -1) {
|
||||
start_wdog(30);
|
||||
ExecuteEnvironmentFunctions();
|
||||
}
|
||||
Bootloader(getc);
|
||||
return (1);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
.include "${.CURDIR}/../Makefile.inc"
|
||||
|
||||
SOC?=at91rm9200
|
||||
|
||||
LIB= at91
|
||||
INTERNALLIB=
|
||||
SRCS=${SOC}_lowlevel.c delay.c eeprom.c emac.c emac_init.c getc.c \
|
||||
putchar.c printf.c reset.c spi_flash.c xmodem.c \
|
||||
sd-card.c strcvt.c strlen.c strcmp.c memcpy.c strcpy.c \
|
||||
memset.c memcmp.c
|
||||
SRCS+=ashldi3.c divsi3.S
|
||||
MAN=
|
||||
|
||||
.if ${MK_TAG_LIST} != "no"
|
||||
CFLAGS += -I${.CURDIR}/.. -DSUPPORT_TAG_LIST
|
||||
SRCS+=tag_list.c
|
||||
.endif
|
||||
|
||||
.include <bsd.lib.mk>
|
@ -1,129 +0,0 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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, 0x3000
|
||||
.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:
|
||||
#ifdef BOOT_IIC
|
||||
.long (TWI_EEPROM_SIZE >> 9)
|
||||
#else
|
||||
#ifdef BOOT_BWCT
|
||||
.long ((528 << 17) | (13 << 13) | (12 * 2))
|
||||
#else
|
||||
.long ((1056 << 17) | (13 << 13) | (12 * 2))
|
||||
#endif
|
||||
#endif
|
||||
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
|
||||
#ifndef BOOT_BOOT0
|
||||
ldr r1, = SVC_STACK_USE
|
||||
mov sp, r1 @ ; Move the stack to SDRAM
|
||||
#endif
|
||||
|
||||
/* Start execution at main */
|
||||
.extern main
|
||||
_main:
|
||||
__main:
|
||||
bl main
|
||||
/* main should not return. If it does, spin forever */
|
||||
infiniteLoop:
|
||||
b infiniteLoop
|
||||
|
||||
#ifdef BOOT_COMMANDS
|
||||
/* the following section is used to store boot commands in */
|
||||
/* non-volatile memory. */
|
||||
|
||||
.global BootCommandSection
|
||||
BootCommandSection:
|
||||
#ifdef SUPPORT_LINUX
|
||||
.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 " "
|
||||
#else
|
||||
#if 1
|
||||
.string "m 42 53 44 0 0 1"
|
||||
.string "ip 206 168 13 194"
|
||||
.string "server_ip 206 168 13 207"
|
||||
.string "tftp 0x20000000 kernel.bin"
|
||||
.string "e 0x20000000"
|
||||
#else
|
||||
.string "m 42 53 44 0 0 1"
|
||||
.string "k 0x20000000"
|
||||
.string "e 0x20000000"
|
||||
#endif
|
||||
.word 0
|
||||
#endif
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,223 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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 provide by Kwikbyte who specifically
|
||||
* disclaimed copyright on the code.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "at91rm9200.h"
|
||||
#include "at91rm9200_lowlevel.h"
|
||||
|
||||
extern int __bss_start__[];
|
||||
extern int __bss_end__[];
|
||||
|
||||
#define BAUD 115200
|
||||
#define AT91C_US_ASYNC_MODE (AT91C_US_USMODE_NORMAL | AT91C_US_NBSTOP_1_BIT | \
|
||||
AT91C_US_PAR_NONE | AT91C_US_CHRL_8_BITS | AT91C_US_CLKS_CLOCK)
|
||||
|
||||
/*
|
||||
* void DefaultSystemInit(void)
|
||||
* Load the system with sane values based on how the system is configured.
|
||||
* at91rm9200_lowlevel.h is expected to define the necessary parameters.
|
||||
*/
|
||||
void
|
||||
_init(void)
|
||||
{
|
||||
int *i;
|
||||
|
||||
AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU;
|
||||
AT91PS_PDC pPDC = (AT91PS_PDC)&(pUSART->US_RPR);
|
||||
|
||||
register unsigned value;
|
||||
volatile sdram_size_t *p = (sdram_size_t *)SDRAM_BASE;
|
||||
|
||||
AT91C_BASE_ST->ST_RTMR = 1;
|
||||
#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;
|
||||
AT91C_BASE_PIOC->PIO_OER = AT91C_PIO_PC10;
|
||||
AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC10;
|
||||
#endif
|
||||
|
||||
#if defined(BOOT_KB920X)
|
||||
AT91C_BASE_PIOC->PIO_PER = AT91C_PIO_PC18 | AT91C_PIO_PC19 |
|
||||
AT91C_PIO_PC20;
|
||||
AT91C_BASE_PIOC->PIO_OER = AT91C_PIO_PC18 | AT91C_PIO_PC19 |
|
||||
AT91C_PIO_PC20;
|
||||
AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC18 | AT91C_PIO_PC19 |
|
||||
AT91C_PIO_PC20;
|
||||
AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC18;
|
||||
#endif
|
||||
|
||||
// configure clocks
|
||||
// assume:
|
||||
// main osc = 10Mhz
|
||||
// PLLB configured for 96MHz (48MHz after div)
|
||||
// CSS = PLLB
|
||||
// set PLLA = 180MHz
|
||||
// assume main osc = 10Mhz
|
||||
// div = 5 , out = 2 (150MHz = 240MHz)
|
||||
value = AT91C_BASE_CKGR->CKGR_PLLAR;
|
||||
value &= ~(AT91C_CKGR_DIVA | AT91C_CKGR_OUTA | AT91C_CKGR_MULA);
|
||||
value |= OSC_MAIN_FREQ_DIV | AT91C_CKGR_OUTA_2 | AT91C_CKGR_SRCA |
|
||||
((OSC_MAIN_MULT - 1) << 16);
|
||||
AT91C_BASE_CKGR->CKGR_PLLAR = value;
|
||||
|
||||
// wait for lock
|
||||
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA))
|
||||
continue;
|
||||
|
||||
// change divider = 3, pres = 1
|
||||
value = AT91C_BASE_PMC->PMC_MCKR;
|
||||
value &= ~(AT91C_PMC_MDIV | AT91C_PMC_PRES);
|
||||
value |= AT91C_PMC_MDIV_3 | AT91C_PMC_PRES_CLK;
|
||||
AT91C_BASE_PMC->PMC_MCKR = value;
|
||||
|
||||
// wait for update
|
||||
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY))
|
||||
continue;
|
||||
|
||||
// change CSS = PLLA
|
||||
value &= ~AT91C_PMC_CSS;
|
||||
value |= AT91C_PMC_CSS_PLLA_CLK;
|
||||
AT91C_BASE_PMC->PMC_MCKR = value;
|
||||
|
||||
// wait for update
|
||||
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY))
|
||||
continue;
|
||||
|
||||
#ifdef BOOT_KB920X
|
||||
// setup flash access (allow ample margin)
|
||||
// 9 wait states, 1 setup, 1 hold, 1 float for 8-bit device
|
||||
((AT91PS_SMC2)AT91C_BASE_SMC2)->SMC2_CSR[0] =
|
||||
AT91C_SMC2_WSEN |
|
||||
(9 & AT91C_SMC2_NWS) |
|
||||
((1 << 8) & AT91C_SMC2_TDF) |
|
||||
AT91C_SMC2_DBW_8 |
|
||||
((1 << 24) & AT91C_SMC2_RWSETUP) |
|
||||
((1 << 29) & AT91C_SMC2_RWHOLD);
|
||||
#endif
|
||||
|
||||
// setup SDRAM access
|
||||
// EBI chip-select register (CS1 = SDRAM controller)
|
||||
// 9 col, 13row, 4 bank, CAS2
|
||||
// write recovery = 2 (Twr)
|
||||
// row cycle = 5 (Trc)
|
||||
// precharge delay = 2 (Trp)
|
||||
// row to col delay 2 (Trcd)
|
||||
// active to precharge = 4 (Tras)
|
||||
// exit self refresh to active = 6 (Txsr)
|
||||
value = ((AT91PS_EBI)AT91C_BASE_EBI)->EBI_CSA;
|
||||
value &= ~AT91C_EBI_CS1A;
|
||||
value |= AT91C_EBI_CS1A_SDRAMC;
|
||||
AT91C_BASE_EBI->EBI_CSA = value;
|
||||
|
||||
AT91C_BASE_SDRC->SDRC_CR =
|
||||
#if defined(KB9202_B) || defined(SDRAM_128M)
|
||||
AT91C_SDRC_NC_10 |
|
||||
#else
|
||||
AT91C_SDRC_NC_9 |
|
||||
#endif
|
||||
AT91C_SDRC_NR_13 |
|
||||
AT91C_SDRC_NB_4_BANKS |
|
||||
AT91C_SDRC_CAS_2 |
|
||||
((2 << 7) & AT91C_SDRC_TWR) |
|
||||
((5 << 11) & AT91C_SDRC_TRC) |
|
||||
((2 << 15) & AT91C_SDRC_TRP) |
|
||||
((2 << 19) & AT91C_SDRC_TRCD) |
|
||||
((4 << 23) & AT91C_SDRC_TRAS) |
|
||||
((6 << 27) & AT91C_SDRC_TXSR);
|
||||
|
||||
// Step 1: We assume 200us of idle time.
|
||||
// Step 2: Issue an all banks precharge command
|
||||
AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_PRCGALL_CMD;
|
||||
*p = 0;
|
||||
|
||||
// Step 3: Issue 8 Auto-refresh (CBR) cycles
|
||||
AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_RFSH_CMD;
|
||||
*p = 0;
|
||||
*p = 0;
|
||||
*p = 0;
|
||||
*p = 0;
|
||||
*p = 0;
|
||||
*p = 0;
|
||||
*p = 0;
|
||||
*p = 0;
|
||||
|
||||
// Step 4: Issue an Mode Set Register (MRS) cycle to program in
|
||||
// the parameters that we setup in the SDRC_CR register above.
|
||||
AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_LMR_CMD;
|
||||
*p = 0;
|
||||
|
||||
// Step 5: set the refresh timer and access memory to start it
|
||||
// running. We have to wait 3 clocks after the LMR_CMD above,
|
||||
// and this fits the bill nicely.
|
||||
AT91C_BASE_SDRC->SDRC_TR = 7 * AT91C_MASTER_CLOCK / 1000000;
|
||||
*p = 0;
|
||||
|
||||
// Step 6: Set normal mode.
|
||||
AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_NORMAL_CMD;
|
||||
*p = 0;
|
||||
|
||||
#if SDRAM_WIDTH == AT91C_SDRC_DBW_32_BITS
|
||||
// Turn on the upper 16 bits on the SDRAM bus.
|
||||
AT91C_BASE_PIOC->PIO_ASR = 0xffff0000;
|
||||
AT91C_BASE_PIOC->PIO_PDR = 0xffff0000;
|
||||
#endif
|
||||
// Configure DBGU -use local routine optimized for space
|
||||
AT91C_BASE_PIOA->PIO_ASR = AT91C_PIO_PA31 | AT91C_PIO_PA30;
|
||||
AT91C_BASE_PIOA->PIO_PDR = AT91C_PIO_PA31 | AT91C_PIO_PA30;
|
||||
pUSART->US_IDR = (unsigned int) -1;
|
||||
pUSART->US_CR =
|
||||
AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;
|
||||
pUSART->US_BRGR = ((((AT91C_MASTER_CLOCK*10)/(BAUD*16))+5)/10);
|
||||
pUSART->US_TTGR = 0;
|
||||
pPDC->PDC_PTCR = AT91C_PDC_RXTDIS;
|
||||
pPDC->PDC_PTCR = AT91C_PDC_TXTDIS;
|
||||
pPDC->PDC_TNPR = 0;
|
||||
pPDC->PDC_TNCR = 0;
|
||||
|
||||
pPDC->PDC_RNPR = 0;
|
||||
pPDC->PDC_RNCR = 0;
|
||||
|
||||
pPDC->PDC_TPR = 0;
|
||||
pPDC->PDC_TCR = 0;
|
||||
|
||||
pPDC->PDC_RPR = 0;
|
||||
pPDC->PDC_RCR = 0;
|
||||
|
||||
pPDC->PDC_PTCR = AT91C_PDC_RXTEN;
|
||||
pPDC->PDC_PTCR = AT91C_PDC_TXTEN;
|
||||
|
||||
pUSART->US_MR = AT91C_US_ASYNC_MODE;
|
||||
pUSART->US_CR = AT91C_US_TXEN;
|
||||
pUSART->US_CR = AT91C_US_RXEN;
|
||||
|
||||
/* Zero BSS now that we have memory setup */
|
||||
i = (int *)__bss_start__;
|
||||
while (i < (int *)__bss_end__)
|
||||
*i++ = 0;
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _AT91RM9200_LOWLEVEL_H_
|
||||
#define _AT91RM9200_LOWLEVEL_H_
|
||||
|
||||
/* default system config parameters */
|
||||
|
||||
#define SDRAM_BASE 0x20000000
|
||||
|
||||
#ifdef BOOT_KB920X
|
||||
/* 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
|
||||
typedef unsigned short sdram_size_t;
|
||||
#define OSC_MAIN_MULT 90
|
||||
#endif
|
||||
|
||||
#ifdef BOOT_CENTIPAD
|
||||
/* 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
|
||||
typedef unsigned short sdram_size_t;
|
||||
#define OSC_MAIN_MULT 90
|
||||
#endif
|
||||
|
||||
#ifdef BOOT_BWCT
|
||||
/* 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_32_BITS
|
||||
typedef unsigned int sdram_size_t;
|
||||
#define OSC_MAIN_MULT 45
|
||||
#endif
|
||||
|
||||
#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_32_BITS
|
||||
typedef unsigned int sdram_size_t;
|
||||
#define OSC_MAIN_MULT 45
|
||||
#endif
|
||||
|
||||
/* Master clock frequency at power-up */
|
||||
#define AT91C_MASTER_CLOCK 60000000
|
||||
|
||||
/* #define GetSeconds() (AT91C_BASE_RTC->RTC_TIMR & AT91C_RTC_SEC) */
|
||||
#define GetSeconds() (AT91C_BASE_ST->ST_CRTR >> 15)
|
||||
|
||||
extern void _init(void);
|
||||
|
||||
#endif /* _AT91RM9200_LOWLEVEL_H_ */
|
@ -1,43 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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 provide by Kwikbyte who specifically
|
||||
* disclaimed copyright on the code.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "at91rm9200.h"
|
||||
#include "spi_flash.h"
|
||||
#include "lib.h"
|
||||
|
||||
void
|
||||
Delay(int us)
|
||||
{
|
||||
unsigned later, now;
|
||||
|
||||
now = AT91C_BASE_ST->ST_CRTR;
|
||||
later = (now + us / 25 + 1) & AT91C_ST_CRTV;
|
||||
while (later != AT91C_BASE_ST->ST_CRTR)
|
||||
continue;
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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_PIO_PA25 | AT91C_PIO_PA26;
|
||||
pPio->PIO_PDR = AT91C_PIO_PA25 | AT91C_PIO_PA26;
|
||||
|
||||
pPio->PIO_MDDR = ~AT91C_PIO_PA25;
|
||||
pPio->PIO_MDER = AT91C_PIO_PA25;
|
||||
|
||||
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
|
||||
*/
|
||||
int
|
||||
ReadEEPROM(unsigned ee_off, unsigned char *data_addr, unsigned size)
|
||||
{
|
||||
const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
|
||||
unsigned int status;
|
||||
unsigned int count;
|
||||
|
||||
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_off;
|
||||
|
||||
// Start transfer
|
||||
twiPtr->TWI_CR = AT91C_TWI_START;
|
||||
|
||||
status = twiPtr->TWI_SR;
|
||||
|
||||
while (size-- > 1){
|
||||
// Wait RHR Holding register is full
|
||||
count = 1000000;
|
||||
while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY) && --count > 0)
|
||||
continue;
|
||||
if (count <= 0)
|
||||
return -1;
|
||||
|
||||
// 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .KB_C_FN_DEFINITION_START
|
||||
* void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size)
|
||||
* This global function writes data to the eeprom at ee_off 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_off, char *data_addr, unsigned size)
|
||||
{
|
||||
const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
|
||||
unsigned status;
|
||||
unsigned char test_data;
|
||||
|
||||
while (size--) {
|
||||
if (!(ee_off & 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_off++;
|
||||
|
||||
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_off, &test_data, 1);
|
||||
}
|
||||
|
||||
putchar('\r');
|
||||
putchar('\n');
|
||||
}
|
@ -1,575 +0,0 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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 "at91rm9200_lowlevel.h"
|
||||
#include "emac.h"
|
||||
#include "lib.h"
|
||||
|
||||
/* ****************************** GLOBALS *************************************/
|
||||
|
||||
/* ********************** PRIVATE FUNCTIONS/DATA ******************************/
|
||||
|
||||
static receive_descriptor_t *p_rxBD;
|
||||
static unsigned short localPort;
|
||||
static unsigned short serverPort;
|
||||
static unsigned serverMACSet;
|
||||
static unsigned localIPSet, serverIPSet;
|
||||
static unsigned lastSize;
|
||||
static unsigned char serverMACAddr[6];
|
||||
static unsigned char localIPAddr[4], serverIPAddr[4];
|
||||
static int ackBlock;
|
||||
static char *dlAddress;
|
||||
|
||||
static unsigned transmitBuffer[1024 / sizeof(unsigned)];
|
||||
static unsigned tftpSendPacket[256 / sizeof(unsigned)];
|
||||
|
||||
/*
|
||||
* .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(unsigned short *p, int len)
|
||||
{
|
||||
unsigned i, t;
|
||||
|
||||
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);
|
||||
|
||||
memcpy(p_ARP->src_mac, 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);
|
||||
|
||||
memcpy(p_ARP->sender_mac, localMACAddr, 6);
|
||||
memcpy(p_ARP->sender_ip, localIPAddr, 4);
|
||||
p_memset((char*)p_ARP->target_mac, 0, 6);
|
||||
memcpy(p_ARP->target_ip, serverIPAddr, 4);
|
||||
|
||||
// wait until transmit is available
|
||||
while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ))
|
||||
continue;
|
||||
|
||||
*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;
|
||||
|
||||
memcpy(macHdr->dest_mac, serverMACAddr, 6);
|
||||
memcpy(macHdr->src_mac, localMACAddr, 6);
|
||||
macHdr->proto_mac = SWAP16(PROTOCOL_IP);
|
||||
|
||||
ipHdr = (ip_header_t*)&macHdr->packet_length;
|
||||
|
||||
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;
|
||||
|
||||
memcpy(ipHdr->ip_src, localIPAddr, 4);
|
||||
memcpy(ipHdr->ip_dst, serverIPAddr, 4);
|
||||
|
||||
ipHdr->ip_sum = SWAP16(IP_checksum((unsigned short*)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;
|
||||
|
||||
memcpy((char *)udpHdr+8, tftpData, tftpLength);
|
||||
|
||||
t_checksum = IP_checksum((unsigned short*)ipHdr + 6, (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))
|
||||
continue;
|
||||
|
||||
*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 = TFTP_RRQ_OPCODE;
|
||||
|
||||
cPtr = (char*)&(tftpHeader.block_num);
|
||||
|
||||
ePtr = strcpy(cPtr, filename);
|
||||
mPtr = 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(unsigned char *data, unsigned short block_num, unsigned short len)
|
||||
{
|
||||
tftp_header_t tftpHeader;
|
||||
|
||||
if (block_num == (ackBlock + 1)) {
|
||||
++ackBlock;
|
||||
memcpy(dlAddress, data, len);
|
||||
dlAddress += len;
|
||||
lastSize += len;
|
||||
if (ackBlock % 128 == 0)
|
||||
printf("tftp: %u kB\r", lastSize / 1024);
|
||||
}
|
||||
tftpHeader.opcode = TFTP_ACK_OPCODE;
|
||||
tftpHeader.block_num = SWAP16(ackBlock);
|
||||
Send_TFTP_Packet((char*)&tftpHeader, 4);
|
||||
if (len < 512) {
|
||||
ackBlock = -2;
|
||||
printf("tftp: %u byte\n", lastSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .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 int
|
||||
CheckForNewPacket(ip_header_t *pHeader)
|
||||
{
|
||||
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 (0);
|
||||
process = i;
|
||||
|
||||
pFrameType = (unsigned short *)((p_rxBD[i].address & 0xFFFFFFFC) + 12);
|
||||
pData = (char *)(p_rxBD[i].address & 0xFFFFFFFC);
|
||||
|
||||
switch (*pFrameType) {
|
||||
|
||||
case SWAP16(PROTOCOL_ARP):
|
||||
p_ARP = (arp_header_t*)pData;
|
||||
if (p_ARP->operation == SWAP16(ARP_REPLY)) {
|
||||
// check if new server info is available
|
||||
if ((!serverMACSet) &&
|
||||
(!(p_memcmp((char*)p_ARP->sender_ip,
|
||||
(char*)serverIPAddr, 4)))) {
|
||||
|
||||
serverMACSet = 1;
|
||||
memcpy(serverMACAddr, p_ARP->sender_mac, 6);
|
||||
}
|
||||
} else if (p_ARP->operation == SWAP16(ARP_REQUEST)) {
|
||||
// ARP REPLY operation
|
||||
p_ARP->operation = SWAP16(ARP_REPLY);
|
||||
|
||||
// Fill the dest address and src address
|
||||
for (i = 0; i <6; i++) {
|
||||
// swap ethernet dest address and ethernet src address
|
||||
pData[i] = pData[i+6];
|
||||
pData[i+6] = localMACAddr[i];
|
||||
// swap sender ethernet address and target ethernet address
|
||||
pData[i+22] = localMACAddr[i];
|
||||
pData[i+32] = pData[i+6];
|
||||
}
|
||||
|
||||
// swap sender IP address and target IP address
|
||||
for (i = 0; i<4; i++) {
|
||||
pData[i+38] = pData[i+28];
|
||||
pData[i+28] = localIPAddr[i];
|
||||
}
|
||||
|
||||
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 SWAP16(PROTOCOL_IP):
|
||||
pIpHeader = (ip_header_t*)(pData + 14);
|
||||
memcpy(pHeader, pIpHeader, sizeof(ip_header_t));
|
||||
|
||||
if (pIpHeader->ip_p == 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 != 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,
|
||||
SWAP16(tftpHdr->block_num),
|
||||
SWAP16(udpHdr->udp_len) - 12);
|
||||
}
|
||||
}
|
||||
p_rxBD[process].address &= ~0x01;
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .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
|
||||
*/
|
||||
#ifndef BOOT_BWCT
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* .KB_C_FN_DEFINITION_START
|
||||
* unsigned short AT91F_MII_WritePhy (AT91PS_EMAC pEmac, unsigned char addr, unsigned short s)
|
||||
* This private function writes the PHY device.
|
||||
* .KB_C_FN_DEFINITION_END
|
||||
*/
|
||||
#ifdef BOOT_TSC
|
||||
static unsigned short
|
||||
AT91F_MII_WritePhy (AT91PS_EMAC pEmac, unsigned char addr, unsigned short s)
|
||||
{
|
||||
unsigned value = 0x50020000 | (addr << 18) | s;
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* .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)
|
||||
{
|
||||
#if defined(BOOT_TSC) || defined(BOOT_KB920X) || defined(BOOT_CENTIPAD)
|
||||
unsigned short stat2;
|
||||
#endif
|
||||
unsigned update;
|
||||
#ifdef BOOT_TSC
|
||||
unsigned sec;
|
||||
int i;
|
||||
#endif
|
||||
#ifdef BOOT_BWCT
|
||||
/* hardcoded link speed since we connect a switch via MII */
|
||||
update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
|
||||
update |= AT91C_EMAC_SPD;
|
||||
update |= AT91C_EMAC_FD;
|
||||
#endif
|
||||
#if defined(BOOT_KB920X) || defined(BOOT_CENTIPAD)
|
||||
stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
|
||||
if (!(stat2 & MII_STS2_LINK))
|
||||
return ;
|
||||
update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
|
||||
if (stat2 & MII_STS2_100TX)
|
||||
update |= AT91C_EMAC_SPD;
|
||||
if (stat2 & MII_STS2_FDX)
|
||||
update |= AT91C_EMAC_FD;
|
||||
#endif
|
||||
#ifdef BOOT_TSC
|
||||
while (1) {
|
||||
for (i = 0; i < 10; i++) {
|
||||
stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS_REG);
|
||||
if (stat2 & MII_STS_LINK_STAT)
|
||||
break;
|
||||
printf(".");
|
||||
sec = GetSeconds();
|
||||
while (GetSeconds() == sec)
|
||||
continue;
|
||||
}
|
||||
if (stat2 & MII_STS_LINK_STAT)
|
||||
break;
|
||||
printf("Resetting MII...");
|
||||
AT91F_MII_WritePhy(pEmac, 0x0, 0x8000);
|
||||
while (AT91F_MII_ReadPhy(pEmac, 0x0) & 0x8000) continue;
|
||||
}
|
||||
printf("emac: link");
|
||||
stat2 = AT91F_MII_ReadPhy(pEmac, MII_SPEC_STS_REG);
|
||||
update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
|
||||
if (stat2 & (MII_SSTS_100FDX | MII_SSTS_100HDX)) {
|
||||
printf(" 100TX");
|
||||
update |= AT91C_EMAC_SPD;
|
||||
}
|
||||
if (stat2 & (MII_SSTS_100FDX | MII_SSTS_10FDX)) {
|
||||
printf(" FDX");
|
||||
update |= AT91C_EMAC_FD;
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
pEmac->EMAC_CFG = 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;
|
||||
|
||||
p_rxBD = (receive_descriptor_t*)RX_BUFFER_START;
|
||||
localPort = SWAP16(0x8002);
|
||||
|
||||
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;
|
||||
|
||||
if (!(pEmac->EMAC_SR & AT91C_EMAC_LINK))
|
||||
MII_GetLinkSpeed(pEmac);
|
||||
|
||||
pEmac->EMAC_RBQP = (unsigned) p_rxBD;
|
||||
pEmac->EMAC_RSR |= (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
|
||||
pEmac->EMAC_CTL = AT91C_EMAC_TE | AT91C_EMAC_RE;
|
||||
|
||||
pEmac->EMAC_TAR = (unsigned)transmitBuffer;
|
||||
}
|
||||
|
||||
|
||||
/* ************************** GLOBAL FUNCTIONS ********************************/
|
||||
|
||||
/*
|
||||
* .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[0] = (address >> 24) & 0xFF;
|
||||
serverIPAddr[1] = (address >> 16) & 0xFF;
|
||||
serverIPAddr[2] = (address >> 8) & 0xFF;
|
||||
serverIPAddr[3] = (address >> 0) & 0xFF;
|
||||
|
||||
serverIPSet = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .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[0] = (address >> 24) & 0xFF;
|
||||
localIPAddr[1] = (address >> 16) & 0xFF;
|
||||
localIPAddr[2] = (address >> 8) & 0xFF;
|
||||
localIPAddr[3] = (address >> 0) & 0xFF;
|
||||
|
||||
localIPSet = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .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)
|
||||
{
|
||||
ip_header_t IpHeader;
|
||||
unsigned thisSeconds;
|
||||
int timeout;
|
||||
|
||||
if ((!localMACSet) || (!localIPSet) || (!serverIPSet))
|
||||
return ;
|
||||
|
||||
AT91F_EmacEntry();
|
||||
GetServerAddress();
|
||||
dlAddress = (char*)address;
|
||||
lastSize = 0;
|
||||
timeout = 10;
|
||||
thisSeconds = (GetSeconds() + 2) % 32;
|
||||
serverPort = SWAP16(69);
|
||||
++localPort;
|
||||
ackBlock = -1;
|
||||
|
||||
while (timeout) {
|
||||
if (CheckForNewPacket(&IpHeader)) {
|
||||
if (ackBlock == -2)
|
||||
break;
|
||||
timeout = 10;
|
||||
thisSeconds = (GetSeconds() + 2) % 32;
|
||||
} else if (GetSeconds() == thisSeconds) {
|
||||
--timeout;
|
||||
thisSeconds = (GetSeconds() + 2) % 32;
|
||||
if (!serverMACSet)
|
||||
GetServerAddress();
|
||||
else if (ackBlock == -1)
|
||||
TFTP_RequestFile(filename);
|
||||
else {
|
||||
// Be sure to send a NAK, which is done by
|
||||
// ACKing the last block we got.
|
||||
TFTP_ACK_Data(0, ackBlock, 512);
|
||||
printf("\nNAK %u\n", ackBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (timeout == 0)
|
||||
printf("TFTP TIMEOUT!\n");
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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 EMAC_SetMACAddress(unsigned char addr[6]);
|
||||
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;
|
||||
|
||||
// Preswap bytes
|
||||
#define TFTP_RRQ_OPCODE 0x0100
|
||||
#define TFTP_WRQ_OPCODE 0x0200
|
||||
#define TFTP_DATA_OPCODE 0x0300
|
||||
#define TFTP_ACK_OPCODE 0x0400
|
||||
#define TFTP_ERROR_OPCODE 0x0500
|
||||
|
||||
/* MII registers definition */
|
||||
#define MII_STS_REG 0x01
|
||||
#define MII_STS_LINK_STAT 0x04
|
||||
#if defined(BOOT_KB920X) || defined(BOOT_CENTIPAD)
|
||||
#define MII_STS2_REG 0x11
|
||||
#define MII_STS2_LINK 0x400
|
||||
#define MII_STS2_100TX 0x4000
|
||||
#define MII_STS2_FDX 0x200
|
||||
#else
|
||||
#define MII_SPEC_STS_REG 0x11
|
||||
#define MII_SSTS_100FDX 0x8000
|
||||
#define MII_SSTS_100HDX 0x4000
|
||||
#define MII_SSTS_10FDX 0x2000
|
||||
#define MII_SSTS_10HDX 0x1000
|
||||
#endif
|
||||
|
||||
extern unsigned char localMACAddr[6];
|
||||
extern unsigned localMAClow, localMAChigh;
|
||||
extern unsigned localMACSet;
|
||||
#define EMAC_Init()
|
||||
|
||||
#endif /* _EMAC_H_ */
|
@ -1,117 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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 provide by Kwikbyte who specifically
|
||||
* disclaimed copyright on the code.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
******************************************************************************/
|
||||
|
||||
#include "at91rm9200.h"
|
||||
#include "at91rm9200_lowlevel.h"
|
||||
#include "emac.h"
|
||||
#include "lib.h"
|
||||
|
||||
/* ****************************** GLOBALS *************************************/
|
||||
|
||||
unsigned localMACSet;
|
||||
unsigned char localMACAddr[6];
|
||||
unsigned localMAClow, localMAChigh;
|
||||
|
||||
/* ********************** PRIVATE FUNCTIONS/DATA ******************************/
|
||||
|
||||
/*
|
||||
* .KB_C_FN_DEFINITION_START
|
||||
* void EMAC_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
|
||||
EMAC_SetMACAddress(unsigned char mac[6])
|
||||
{
|
||||
AT91PS_PMC pPMC = AT91C_BASE_PMC;
|
||||
AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
|
||||
|
||||
/* enable the peripheral clock before using EMAC */
|
||||
pPMC->PMC_PCER = ((unsigned) 1 << AT91C_ID_EMAC);
|
||||
|
||||
memcpy(localMACAddr, mac, 6);
|
||||
localMAClow = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0];
|
||||
localMAChigh = (mac[5] << 8) | mac[4];
|
||||
localMACSet = 1;
|
||||
|
||||
AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_EMAC;
|
||||
AT91C_BASE_PIOA->PIO_ASR =
|
||||
AT91C_PIO_PA14 | AT91C_PIO_PA12 | AT91C_PIO_PA13 |
|
||||
AT91C_PIO_PA8 | AT91C_PIO_PA16 | AT91C_PIO_PA9 |
|
||||
AT91C_PIO_PA10 | AT91C_PIO_PA11 | AT91C_PIO_PA15 |
|
||||
AT91C_PIO_PA7;
|
||||
AT91C_BASE_PIOA->PIO_PDR =
|
||||
AT91C_PIO_PA14 | AT91C_PIO_PA12 | AT91C_PIO_PA13 |
|
||||
AT91C_PIO_PA8 | AT91C_PIO_PA16 | AT91C_PIO_PA9 |
|
||||
AT91C_PIO_PA10 | AT91C_PIO_PA11 | AT91C_PIO_PA15 |
|
||||
AT91C_PIO_PA7;
|
||||
#if defined(BOOT_KB920X) | defined(BOOT_BWCT) /* Really !RMII */
|
||||
AT91C_BASE_PIOB->PIO_BSR =
|
||||
AT91C_PIO_PB12 | AT91C_PIO_PB13 | AT91C_PIO_PB14 |
|
||||
AT91C_PIO_PB15 | AT91C_PIO_PB16 | AT91C_PIO_PB17 |
|
||||
AT91C_PIO_PB18 | AT91C_PIO_PB19;
|
||||
AT91C_BASE_PIOB->PIO_PDR =
|
||||
AT91C_PIO_PB12 | AT91C_PIO_PB13 | AT91C_PIO_PB14 |
|
||||
AT91C_PIO_PB15 | AT91C_PIO_PB16 | AT91C_PIO_PB17 |
|
||||
AT91C_PIO_PB18 | AT91C_PIO_PB19;
|
||||
#endif
|
||||
pEmac->EMAC_CTL = 0;
|
||||
|
||||
pEmac->EMAC_CFG = (pEmac->EMAC_CFG & ~(AT91C_EMAC_CLK)) |
|
||||
#ifdef BOOT_TSC
|
||||
AT91C_EMAC_RMII |
|
||||
#endif
|
||||
AT91C_EMAC_CLK_HCLK_32 | AT91C_EMAC_CAF;
|
||||
// the sequence write EMAC_SA1L and write EMAC_SA1H must be respected
|
||||
pEmac->EMAC_SA1L = localMAClow;
|
||||
pEmac->EMAC_SA1H = localMAChigh;
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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$
|
||||
*/
|
||||
|
||||
#include "at91rm9200.h"
|
||||
#include "at91rm9200_lowlevel.h"
|
||||
#include "lib.h"
|
||||
|
||||
/*
|
||||
* int getc(int seconds)
|
||||
*
|
||||
* Reads a character from the DBGU port, if one is available within about
|
||||
* seconds seconds. It assumes that DBGU has already been initialized.
|
||||
*/
|
||||
int
|
||||
getc(int seconds)
|
||||
{
|
||||
AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU;
|
||||
unsigned thisSecond;
|
||||
|
||||
// Clamp to 20s
|
||||
if (seconds > 20)
|
||||
seconds = 20;
|
||||
thisSecond = GetSeconds();
|
||||
seconds = thisSecond + seconds;
|
||||
do {
|
||||
if ((pUSART->US_CSR & AT91C_US_RXRDY))
|
||||
return (pUSART->US_RHR & 0xFF);
|
||||
thisSecond = GetSeconds();
|
||||
} while (thisSecond != seconds);
|
||||
return (-1);
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef ARM_BOOT_LIB_H
|
||||
#define ARM_BOOT_LIB_H
|
||||
|
||||
int getc(int);
|
||||
void putchar(int);
|
||||
void xputchar(int);
|
||||
void printf(const char *fmt,...);
|
||||
|
||||
/* The following function write eeprom at ee_addr using data */
|
||||
/* from data_add for size bytes. */
|
||||
int ReadEEPROM(unsigned eeoff, unsigned char *data_addr, unsigned size);
|
||||
void WriteEEPROM(unsigned eeoff, char *data_addr, unsigned size);
|
||||
void InitEEPROM(void);
|
||||
|
||||
/* XMODEM protocol */
|
||||
int xmodem_rx(char *dst);
|
||||
|
||||
/* */
|
||||
void start_wdog(int n);
|
||||
void reset(void);
|
||||
|
||||
/* Delay us */
|
||||
void Delay(int us);
|
||||
|
||||
#define ToASCII(x) ((x > 9) ? (x + 'A' - 0xa) : (x + '0'))
|
||||
|
||||
int p_IsWhiteSpace(char cValue);
|
||||
unsigned p_HexCharValue(char cValue);
|
||||
unsigned p_ASCIIToHex(const char *buf);
|
||||
unsigned p_ASCIIToDec(const char *buf);
|
||||
|
||||
void p_memset(char *buffer, char value, int size);
|
||||
int p_strlen(const char *buffer);
|
||||
char *strcpy(char *to, const char *from);
|
||||
void memcpy(void *to, const void *from, unsigned size);
|
||||
int p_memcmp(const char *to, const char *from, unsigned size);
|
||||
int strcmp(const char *to, const char *from);
|
||||
|
||||
#endif
|
@ -1,277 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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 provide by Kwikbyte who specifically
|
||||
* disclaimed copyright on the code.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __LIBAT91RM9200_H
|
||||
#define __LIBAT91RM9200_H
|
||||
|
||||
#include "at91rm9200.h"
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PMC_EnablePeriphClock
|
||||
//* \brief Enable peripheral clock
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_PMC_EnablePeriphClock (
|
||||
AT91PS_PMC pPMC, // \arg pointer to PMC controller
|
||||
unsigned int periphIds) // \arg IDs of peripherals to enable
|
||||
{
|
||||
pPMC->PMC_PCER = periphIds;
|
||||
}
|
||||
|
||||
/* *****************************************************************************
|
||||
SOFTWARE API FOR PIO
|
||||
***************************************************************************** */
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PIO_CfgPeriph
|
||||
//* \brief Enable pins to be drived by peripheral
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline
|
||||
void AT91F_PIO_CfgPeriph(
|
||||
AT91PS_PIO pPio, // \arg pointer to a PIO controller
|
||||
unsigned int periphAEnable, // \arg PERIPH A to enable
|
||||
unsigned int periphBEnable) // \arg PERIPH B to enable
|
||||
|
||||
{
|
||||
if (periphAEnable)
|
||||
pPio->PIO_ASR = periphAEnable;
|
||||
if (periphBEnable)
|
||||
pPio->PIO_BSR = periphBEnable;
|
||||
pPio->PIO_PDR = (periphAEnable | periphBEnable); // Set in Periph mode
|
||||
}
|
||||
|
||||
/* *****************************************************************************
|
||||
SOFTWARE API FOR MCI
|
||||
***************************************************************************** */
|
||||
//* Classic MCI Data Timeout Register Configuration with 1048576 MCK cycles between 2 data transfer
|
||||
#define AT91C_MCI_DTOR_1MEGA_CYCLES (AT91C_MCI_DTOCYC | AT91C_MCI_DTOMUL)
|
||||
|
||||
//* Classic MCI SDCard Register Configuration with 1-bit data bus on slot A
|
||||
#define AT91C_MCI_MMC_SLOTA (AT91C_MCI_SCDSEL & 0x0)
|
||||
|
||||
//* Classic MCI SDCard Register Configuration with 1-bit data bus on slot B
|
||||
#define AT91C_MCI_MMC_SLOTB (AT91C_MCI_SCDSEL)
|
||||
|
||||
//* Classic MCI SDCard Register Configuration with 4-bit data bus on slot A
|
||||
#define AT91C_MCI_SDCARD_4BITS_SLOTA ( (AT91C_MCI_SCDSEL & 0x0) | AT91C_MCI_SCDBUS )
|
||||
|
||||
//* Classic MCI SDCard Register Configuration with 4-bit data bus on slot B
|
||||
#define AT91C_MCI_SDCARD_4BITS_SLOTB (AT91C_MCI_SCDSEL | AT91C_MCI_SCDBUS)
|
||||
|
||||
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_MCI_Configure
|
||||
//* \brief Configure the MCI
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline
|
||||
void AT91F_MCI_Configure(
|
||||
AT91PS_MCI pMCI, // \arg pointer to a MCI controller
|
||||
unsigned int DTOR_register, // \arg Data Timeout Register to be programmed
|
||||
unsigned int MR_register, // \arg Mode Register to be programmed
|
||||
unsigned int SDCR_register) // \arg SDCard Register to be programmed
|
||||
{
|
||||
//* Reset the MCI
|
||||
pMCI->MCI_CR = AT91C_MCI_MCIEN | AT91C_MCI_PWSEN;
|
||||
|
||||
//* Disable all the interrupts
|
||||
pMCI->MCI_IDR = 0xFFFFFFFF;
|
||||
|
||||
//* Set the Data Timeout Register
|
||||
pMCI->MCI_DTOR = DTOR_register;
|
||||
|
||||
//* Set the Mode Register
|
||||
pMCI->MCI_MR = MR_register;
|
||||
|
||||
//* Set the SDCard Register
|
||||
pMCI->MCI_SDCR = SDCR_register;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_MCI_CfgPMC
|
||||
//* \brief Enable Peripheral clock in PMC for MCI
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_MCI_CfgPMC(void)
|
||||
{
|
||||
AT91F_PMC_EnablePeriphClock(
|
||||
AT91C_BASE_PMC, // PIO controller base address
|
||||
((unsigned int) 1 << AT91C_ID_MCI));
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_MCI_CfgPIO
|
||||
//* \brief Configure PIO controllers to drive MCI signals
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_MCI_CfgPIO(void)
|
||||
{
|
||||
// Configure PIO controllers to periph mode
|
||||
AT91F_PIO_CfgPeriph(
|
||||
AT91C_BASE_PIOA, // PIO controller base address
|
||||
((unsigned int) AT91C_PIO_PA28 ) |
|
||||
((unsigned int) AT91C_PIO_PA29 ) |
|
||||
((unsigned int) AT91C_PIO_PA27 ), // Peripheral A
|
||||
0); // Peripheral B
|
||||
// Configure PIO controllers to periph mode
|
||||
AT91F_PIO_CfgPeriph(
|
||||
AT91C_BASE_PIOB, // PIO controller base address
|
||||
0, // Peripheral A
|
||||
((unsigned int) AT91C_PIO_PB5 ) |
|
||||
((unsigned int) AT91C_PIO_PB3 ) |
|
||||
((unsigned int) AT91C_PIO_PB4 )); // Peripheral B
|
||||
}
|
||||
|
||||
|
||||
/* *****************************************************************************
|
||||
SOFTWARE API FOR PDC
|
||||
***************************************************************************** */
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_SetNextRx
|
||||
//* \brief Set the next receive transfer descriptor
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_PDC_SetNextRx (
|
||||
AT91PS_PDC pPDC, // \arg pointer to a PDC controller
|
||||
char *address, // \arg address to the next bloc to be received
|
||||
unsigned int bytes) // \arg number of bytes to be received
|
||||
{
|
||||
pPDC->PDC_RNPR = (unsigned int) address;
|
||||
pPDC->PDC_RNCR = bytes;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_SetNextTx
|
||||
//* \brief Set the next transmit transfer descriptor
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_PDC_SetNextTx(
|
||||
AT91PS_PDC pPDC, // \arg pointer to a PDC controller
|
||||
char *address, // \arg address to the next bloc to be transmitted
|
||||
unsigned int bytes) // \arg number of bytes to be transmitted
|
||||
{
|
||||
pPDC->PDC_TNPR = (unsigned int) address;
|
||||
pPDC->PDC_TNCR = bytes;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_SetRx
|
||||
//* \brief Set the receive transfer descriptor
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_PDC_SetRx(
|
||||
AT91PS_PDC pPDC, // \arg pointer to a PDC controller
|
||||
char *address, // \arg address to the next bloc to be received
|
||||
unsigned int bytes) // \arg number of bytes to be received
|
||||
{
|
||||
pPDC->PDC_RPR = (unsigned int) address;
|
||||
pPDC->PDC_RCR = bytes;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_SetTx
|
||||
//* \brief Set the transmit transfer descriptor
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_PDC_SetTx(
|
||||
AT91PS_PDC pPDC, // \arg pointer to a PDC controller
|
||||
char *address, // \arg address to the next bloc to be transmitted
|
||||
unsigned int bytes) // \arg number of bytes to be transmitted
|
||||
{
|
||||
pPDC->PDC_TPR = (unsigned int) address;
|
||||
pPDC->PDC_TCR = bytes;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_EnableTx
|
||||
//* \brief Enable transmit
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_PDC_EnableTx(
|
||||
AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
|
||||
{
|
||||
pPDC->PDC_PTCR = AT91C_PDC_TXTEN;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_EnableRx
|
||||
//* \brief Enable receive
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_PDC_EnableRx(
|
||||
AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
|
||||
{
|
||||
pPDC->PDC_PTCR = AT91C_PDC_RXTEN;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_DisableTx
|
||||
//* \brief Disable transmit
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_PDC_DisableTx(
|
||||
AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
|
||||
{
|
||||
pPDC->PDC_PTCR = AT91C_PDC_TXTDIS;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_DisableRx
|
||||
//* \brief Disable receive
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_PDC_DisableRx(
|
||||
AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
|
||||
{
|
||||
pPDC->PDC_PTCR = AT91C_PDC_RXTDIS;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_Open
|
||||
//* \brief Open PDC: disable TX and RX reset transfer descriptors, re-enable RX and TX
|
||||
//*----------------------------------------------------------------------------
|
||||
static inline void
|
||||
AT91F_PDC_Open(
|
||||
AT91PS_PDC pPDC) // \arg pointer to a PDC controller
|
||||
{
|
||||
//* Disable the RX and TX PDC transfer requests
|
||||
AT91F_PDC_DisableRx(pPDC);
|
||||
AT91F_PDC_DisableTx(pPDC);
|
||||
|
||||
//* Reset all Counter register Next buffer first
|
||||
AT91F_PDC_SetNextTx(pPDC, (char *) 0, 0);
|
||||
AT91F_PDC_SetNextRx(pPDC, (char *) 0, 0);
|
||||
AT91F_PDC_SetTx(pPDC, (char *) 0, 0);
|
||||
AT91F_PDC_SetRx(pPDC, (char *) 0, 0);
|
||||
|
||||
//* Enable the RX and TX PDC transfer requests
|
||||
AT91F_PDC_EnableRx(pPDC);
|
||||
AT91F_PDC_EnableTx(pPDC);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,434 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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 provide by Kwikbyte who specifically
|
||||
* disclaimed copyright on the code.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
//*---------------------------------------------------------------------------
|
||||
//* ATMEL Microcontroller Software Support - ROUSSET -
|
||||
//*---------------------------------------------------------------------------
|
||||
//* The software is delivered "AS IS" without warranty or condition of any
|
||||
//* kind, either express, implied or statutory. This includes without
|
||||
//* limitation any warranty or condition with respect to merchantability or
|
||||
//* fitness for any particular purpose, or against the infringements of
|
||||
//* intellectual property rights of others.
|
||||
//*---------------------------------------------------------------------------
|
||||
//* File Name : AT91C_MCI_Device.h
|
||||
//* Object : Data Flash Atmel Description File
|
||||
//* Translator :
|
||||
//*
|
||||
//* 1.0 26/11/02 FB : Creation
|
||||
//*---------------------------------------------------------------------------
|
||||
|
||||
#ifndef __MCI_Device_h
|
||||
#define __MCI_Device_h
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef unsigned int AT91S_MCIDeviceStatus;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define AT91C_CARD_REMOVED 0
|
||||
#define AT91C_MMC_CARD_INSERTED 1
|
||||
#define AT91C_SD_CARD_INSERTED 2
|
||||
|
||||
#define AT91C_NO_ARGUMENT 0x0
|
||||
|
||||
#define AT91C_FIRST_RCA 0xCAFE
|
||||
#define AT91C_MAX_MCI_CARDS 10
|
||||
|
||||
#define AT91C_BUS_WIDTH_1BIT 0x00
|
||||
#define AT91C_BUS_WIDTH_4BITS 0x02
|
||||
|
||||
/* Driver State */
|
||||
#define AT91C_MCI_IDLE 0x0
|
||||
#define AT91C_MCI_TIMEOUT_ERROR 0x1
|
||||
#define AT91C_MCI_RX_SINGLE_BLOCK 0x2
|
||||
#define AT91C_MCI_RX_MULTIPLE_BLOCK 0x3
|
||||
#define AT91C_MCI_RX_STREAM 0x4
|
||||
#define AT91C_MCI_TX_SINGLE_BLOCK 0x5
|
||||
#define AT91C_MCI_TX_MULTIPLE_BLOCK 0x6
|
||||
#define AT91C_MCI_TX_STREAM 0x7
|
||||
|
||||
/* TimeOut */
|
||||
#define AT91C_TIMEOUT_CMDRDY 30
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MMC & SDCard Structures
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*---------------------------------------------*/
|
||||
/* MCI Device Structure Definition */
|
||||
/*---------------------------------------------*/
|
||||
typedef struct _AT91S_MciDevice
|
||||
{
|
||||
volatile unsigned char state;
|
||||
unsigned char SDCard_bus_width;
|
||||
unsigned char IsSDv2;
|
||||
unsigned char IsSDHC;
|
||||
unsigned int RCA; // RCA
|
||||
unsigned int READ_BL_LEN;
|
||||
#ifdef REPORT_SIZE
|
||||
unsigned int Memory_Capacity;
|
||||
#endif
|
||||
} AT91S_MciDevice;
|
||||
|
||||
#include <dev/mmc/mmcreg.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Functions returnals
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define AT91C_CMD_SEND_OK 0 // Command ok
|
||||
#define AT91C_CMD_SEND_ERROR -1 // Command failed
|
||||
#define AT91C_INIT_OK 2 // Init Successful
|
||||
#define AT91C_INIT_ERROR 3 // Init Failed
|
||||
#define AT91C_READ_OK 4 // Read Successful
|
||||
#define AT91C_READ_ERROR 5 // Read Failed
|
||||
#define AT91C_WRITE_OK 6 // Write Successful
|
||||
#define AT91C_WRITE_ERROR 7 // Write Failed
|
||||
#define AT91C_ERASE_OK 8 // Erase Successful
|
||||
#define AT91C_ERASE_ERROR 9 // Erase Failed
|
||||
#define AT91C_CARD_SELECTED_OK 10 // Card Selection Successful
|
||||
#define AT91C_CARD_SELECTED_ERROR 11 // Card Selection Failed
|
||||
|
||||
#define AT91C_MCI_SR_ERROR (AT91C_MCI_UNRE | AT91C_MCI_OVRE | AT91C_MCI_DTOE | \
|
||||
AT91C_MCI_DCRCE | AT91C_MCI_RTOE | AT91C_MCI_RENDE | AT91C_MCI_RCRCE | \
|
||||
AT91C_MCI_RDIRE | AT91C_MCI_RINDE)
|
||||
|
||||
#define MMC_CMDNB (0x1Fu << 0) // Command Number
|
||||
#define MMC_RSPTYP (0x3u << 6) // Response Type
|
||||
#define MMC_RSPTYP_NO (0x0u << 6) // No response
|
||||
#define MMC_RSPTYP_48 (0x1u << 6) // 48-bit response
|
||||
#define MMC_RSPTYP_136 (0x2u << 6) // 136-bit response
|
||||
#define MMC_SPCMD (0x7u << 8) // Special CMD
|
||||
#define MMC_SPCMD_NONE (0x0u << 8) // Not a special CMD
|
||||
#define MMC_SPCMD_INIT (0x1u << 8) // Initialization CMD
|
||||
#define MMC_SPCMD_SYNC (0x2u << 8) // Synchronized CMD
|
||||
#define MMC_SPCMD_IT_CMD (0x4u << 8) // Interrupt command
|
||||
#define MMC_SPCMD_IT_REP (0x5u << 8) // Interrupt response
|
||||
#define MMC_OPDCMD (0x1u << 11) // Open Drain Command
|
||||
#define MMC_MAXLAT (0x1u << 12) // Maximum Latency for Command to respond
|
||||
#define MMC_TRCMD (0x3u << 16) // Transfer CMD
|
||||
#define MMC_TRCMD_NO (0x0u << 16) // No transfer
|
||||
#define MMC_TRCMD_START (0x1u << 16) // Start transfer
|
||||
#define MMC_TRCMD_STOP (0x2u << 16) // Stop transfer
|
||||
#define MMC_TRDIR (0x1u << 18) // Transfer Direction
|
||||
#define MMC_TRTYP (0x3u << 19) // Transfer Type
|
||||
#define MMC_TRTYP_BLOCK (0x0u << 19) // Block Transfer type
|
||||
#define MMC_TRTYP_MULTIPLE (0x1u << 19) // Multiple Block transfer type
|
||||
#define MMC_TRTYP_STREAM (0x2u << 19) // Stream transfer type
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MCI_CMD Register Value
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define POWER_ON_INIT \
|
||||
(0 | MMC_TRCMD_NO | MMC_SPCMD_INIT | MMC_OPDCMD)
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Class 0 & 1 commands: Basic commands and Read Stream commands
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#define GO_IDLE_STATE_CMD \
|
||||
(0 | MMC_TRCMD_NO | MMC_SPCMD_NONE )
|
||||
#define MMC_GO_IDLE_STATE_CMD \
|
||||
(0 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_OPDCMD)
|
||||
#define MMC_SEND_OP_COND_CMD \
|
||||
(1 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
|
||||
MMC_OPDCMD)
|
||||
|
||||
#define ALL_SEND_CID_CMD \
|
||||
(2 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_136)
|
||||
#define MMC_ALL_SEND_CID_CMD \
|
||||
(2 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_136 | \
|
||||
MMC_OPDCMD)
|
||||
|
||||
#define SET_RELATIVE_ADDR_CMD \
|
||||
(3 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
|
||||
MMC_MAXLAT)
|
||||
#define MMC_SET_RELATIVE_ADDR_CMD \
|
||||
(3 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
|
||||
MMC_MAXLAT | MMC_OPDCMD)
|
||||
|
||||
#define SET_DSR_CMD \
|
||||
(4 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_NO | \
|
||||
MMC_MAXLAT) // no tested
|
||||
|
||||
#define SEL_DESEL_CARD_CMD \
|
||||
(7 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
|
||||
MMC_MAXLAT)
|
||||
#define SEND_CSD_CMD \
|
||||
(9 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_136 | \
|
||||
MMC_MAXLAT)
|
||||
#define SEND_CID_CMD \
|
||||
(10 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_136 | \
|
||||
MMC_MAXLAT)
|
||||
#define MMC_READ_DAT_UNTIL_STOP_CMD \
|
||||
(11 | MMC_TRTYP_STREAM | MMC_SPCMD_NONE | \
|
||||
MMC_RSPTYP_48 | MMC_TRDIR | MMC_TRCMD_START | \
|
||||
MMC_MAXLAT)
|
||||
|
||||
#define STOP_TRANSMISSION_CMD \
|
||||
(12 | MMC_TRCMD_STOP | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
|
||||
MMC_MAXLAT)
|
||||
#define STOP_TRANSMISSION_SYNC_CMD \
|
||||
(12 | MMC_TRCMD_STOP | MMC_SPCMD_SYNC | MMC_RSPTYP_48 | \
|
||||
MMC_MAXLAT)
|
||||
#define SEND_STATUS_CMD \
|
||||
(13 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
|
||||
MMC_MAXLAT)
|
||||
#define GO_INACTIVE_STATE_CMD \
|
||||
(15 | MMC_RSPTYP_NO)
|
||||
#define SD_SEND_IF_COND_CMD \
|
||||
(8 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
|
||||
MMC_MAXLAT)
|
||||
//*------------------------------------------------
|
||||
//* Class 2 commands: Block oriented Read commands
|
||||
//*------------------------------------------------
|
||||
|
||||
#define SET_BLOCKLEN_CMD (16 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_MAXLAT )
|
||||
#define READ_SINGLE_BLOCK_CMD (17 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_START | MMC_TRTYP_BLOCK | MMC_TRDIR | MMC_MAXLAT)
|
||||
#define READ_MULTIPLE_BLOCK_CMD (18 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_START | MMC_TRTYP_MULTIPLE | MMC_TRDIR | MMC_MAXLAT)
|
||||
|
||||
//*--------------------------------------------
|
||||
//* Class 3 commands: Sequential write commands
|
||||
//*--------------------------------------------
|
||||
|
||||
#define MMC_WRITE_DAT_UNTIL_STOP_CMD (20 | MMC_TRTYP_STREAM| MMC_SPCMD_NONE | MMC_RSPTYP_48 & ~(MMC_TRDIR) | MMC_TRCMD_START | MMC_MAXLAT ) // MMC
|
||||
|
||||
//*------------------------------------------------
|
||||
//* Class 4 commands: Block oriented write commands
|
||||
//*------------------------------------------------
|
||||
|
||||
#define WRITE_BLOCK_CMD (24 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_START | (MMC_TRTYP_BLOCK & ~(MMC_TRDIR)) | MMC_MAXLAT)
|
||||
#define WRITE_MULTIPLE_BLOCK_CMD (25 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_START | (MMC_TRTYP_MULTIPLE & ~(MMC_TRDIR)) | MMC_MAXLAT)
|
||||
#define PROGRAM_CSD_CMD (27 | MMC_RSPTYP_48 )
|
||||
|
||||
|
||||
//*----------------------------------------
|
||||
//* Class 6 commands: Group Write protect
|
||||
//*----------------------------------------
|
||||
|
||||
#define SET_WRITE_PROT_CMD (28 | MMC_RSPTYP_48 )
|
||||
#define CLR_WRITE_PROT_CMD (29 | MMC_RSPTYP_48 )
|
||||
#define SEND_WRITE_PROT_CMD (30 | MMC_RSPTYP_48 )
|
||||
|
||||
|
||||
//*----------------------------------------
|
||||
//* Class 5 commands: Erase commands
|
||||
//*----------------------------------------
|
||||
|
||||
#define TAG_SECTOR_START_CMD (32 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
#define TAG_SECTOR_END_CMD (33 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
#define MMC_UNTAG_SECTOR_CMD (34 | MMC_RSPTYP_48 )
|
||||
#define MMC_TAG_ERASE_GROUP_START_CMD (35 | MMC_RSPTYP_48 )
|
||||
#define MMC_TAG_ERASE_GROUP_END_CMD (36 | MMC_RSPTYP_48 )
|
||||
#define MMC_UNTAG_ERASE_GROUP_CMD (37 | MMC_RSPTYP_48 )
|
||||
#define ERASE_CMD (38 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT )
|
||||
|
||||
//*----------------------------------------
|
||||
//* Class 7 commands: Lock commands
|
||||
//*----------------------------------------
|
||||
|
||||
#define LOCK_UNLOCK (42 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT) // no tested
|
||||
|
||||
//*-----------------------------------------------
|
||||
// Class 8 commands: Application specific commands
|
||||
//*-----------------------------------------------
|
||||
|
||||
#define APP_CMD (55 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
#define GEN_CMD (56 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT) // no tested
|
||||
|
||||
#define SDCARD_SET_BUS_WIDTH_CMD (6 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
#define SDCARD_STATUS_CMD (13 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
#define SDCARD_SEND_NUM_WR_BLOCKS_CMD (22 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
#define SDCARD_SET_WR_BLK_ERASE_COUNT_CMD (23 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
#define SDCARD_APP_OP_COND_CMD (41 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
#define SDCARD_SET_CLR_CARD_DETECT_CMD (42 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
#define SDCARD_SEND_SCR_CMD (51 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
|
||||
#define SDCARD_APP_ALL_CMD (SDCARD_SET_BUS_WIDTH_CMD +\
|
||||
SDCARD_STATUS_CMD +\
|
||||
SDCARD_SEND_NUM_WR_BLOCKS_CMD +\
|
||||
SDCARD_SET_WR_BLK_ERASE_COUNT_CMD +\
|
||||
SDCARD_APP_OP_COND_CMD +\
|
||||
SDCARD_SET_CLR_CARD_DETECT_CMD +\
|
||||
SDCARD_SEND_SCR_CMD)
|
||||
|
||||
//*----------------------------------------
|
||||
//* Class 9 commands: IO Mode commands
|
||||
//*----------------------------------------
|
||||
|
||||
#define MMC_FAST_IO_CMD (39 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_MAXLAT)
|
||||
#define MMC_GO_IRQ_STATE_CMD (40 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// OCR Register
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define AT91C_VDD_16_17 (1 << 4)
|
||||
#define AT91C_VDD_17_18 (1 << 5)
|
||||
#define AT91C_VDD_18_19 (1 << 6)
|
||||
#define AT91C_VDD_19_20 (1 << 7)
|
||||
#define AT91C_VDD_20_21 (1 << 8)
|
||||
#define AT91C_VDD_21_22 (1 << 9)
|
||||
#define AT91C_VDD_22_23 (1 << 10)
|
||||
#define AT91C_VDD_23_24 (1 << 11)
|
||||
#define AT91C_VDD_24_25 (1 << 12)
|
||||
#define AT91C_VDD_25_26 (1 << 13)
|
||||
#define AT91C_VDD_26_27 (1 << 14)
|
||||
#define AT91C_VDD_27_28 (1 << 15)
|
||||
#define AT91C_VDD_28_29 (1 << 16)
|
||||
#define AT91C_VDD_29_30 (1 << 17)
|
||||
#define AT91C_VDD_30_31 (1 << 18)
|
||||
#define AT91C_VDD_31_32 (1 << 19)
|
||||
#define AT91C_VDD_32_33 (1 << 20)
|
||||
#define AT91C_VDD_33_34 (1 << 21)
|
||||
#define AT91C_VDD_34_35 (1 << 22)
|
||||
#define AT91C_VDD_35_36 (1 << 23)
|
||||
#define AT91C_CCS (1 << 30)
|
||||
#define AT91C_CARD_POWER_UP_DONE (1U << 31)
|
||||
|
||||
#define AT91C_MMC_HOST_VOLTAGE_RANGE (AT91C_VDD_27_28 | AT91C_VDD_28_29 | \
|
||||
AT91C_VDD_29_30 | AT91C_VDD_30_31 | AT91C_VDD_31_32 | AT91C_VDD_32_33)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CURRENT_STATE & READY_FOR_DATA in SDCard Status Register definition (response type R1)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define AT91C_SR_READY_FOR_DATA (1 << 8) // corresponds to buffer empty signalling on the bus
|
||||
#define AT91C_SR_IDLE (0 << 9)
|
||||
#define AT91C_SR_READY (1 << 9)
|
||||
#define AT91C_SR_IDENT (2 << 9)
|
||||
#define AT91C_SR_STBY (3 << 9)
|
||||
#define AT91C_SR_TRAN (4 << 9)
|
||||
#define AT91C_SR_DATA (5 << 9)
|
||||
#define AT91C_SR_RCV (6 << 9)
|
||||
#define AT91C_SR_PRG (7 << 9)
|
||||
#define AT91C_SR_DIS (8 << 9)
|
||||
|
||||
#define AT91C_SR_CARD_SELECTED (AT91C_SR_READY_FOR_DATA + AT91C_SR_TRAN)
|
||||
|
||||
#define MMC_FIRST_RCA 0xCAFE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MMC CSD register header File
|
||||
// CSD_x_xxx_S for shift value for word x
|
||||
// CSD_x_xxx_M for mask value for word x
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// First Response INT <=> CSD[3] : bits 0 to 31
|
||||
#define CSD_3_BIT0_S 0 // [0:0]
|
||||
#define CSD_3_BIT0_M 0x01
|
||||
#define CSD_3_CRC_S 1 // [7:1]
|
||||
#define CSD_3_CRC_M 0x7F
|
||||
#define CSD_3_MMC_ECC_S 8 // [9:8] reserved for MMC compatibility
|
||||
#define CSD_3_MMC_ECC_M 0x03
|
||||
#define CSD_3_FILE_FMT_S 10 // [11:10]
|
||||
#define CSD_3_FILE_FMT_M 0x03
|
||||
#define CSD_3_TMP_WP_S 12 // [12:12]
|
||||
#define CSD_3_TMP_WP_M 0x01
|
||||
#define CSD_3_PERM_WP_S 13 // [13:13]
|
||||
#define CSD_3_PERM_WP_M 0x01
|
||||
#define CSD_3_COPY_S 14 // [14:14]
|
||||
#define CSD_3_COPY_M 0x01
|
||||
#define CSD_3_FILE_FMT_GRP_S 15 // [15:15]
|
||||
#define CSD_3_FILE_FMT_GRP_M 0x01
|
||||
// reserved 16 // [20:16]
|
||||
// reserved 0x1F
|
||||
#define CSD_3_WBLOCK_P_S 21 // [21:21]
|
||||
#define CSD_3_WBLOCK_P_M 0x01
|
||||
#define CSD_3_WBLEN_S 22 // [25:22]
|
||||
#define CSD_3_WBLEN_M 0x0F
|
||||
#define CSD_3_R2W_F_S 26 // [28:26]
|
||||
#define CSD_3_R2W_F_M 0x07
|
||||
#define CSD_3_MMC_DEF_ECC_S 29 // [30:29] reserved for MMC compatibility
|
||||
#define CSD_3_MMC_DEF_ECC_M 0x03
|
||||
#define CSD_3_WP_GRP_EN_S 31 // [31:31]
|
||||
#define CSD_3_WP_GRP_EN_M 0x01
|
||||
|
||||
// Seconde Response INT <=> CSD[2] : bits 32 to 63
|
||||
#define CSD_2_v21_WP_GRP_SIZE_S 0 // [38:32]
|
||||
#define CSD_2_v21_WP_GRP_SIZE_M 0x7F
|
||||
#define CSD_2_v21_SECT_SIZE_S 7 // [45:39]
|
||||
#define CSD_2_v21_SECT_SIZE_M 0x7F
|
||||
#define CSD_2_v21_ER_BLEN_EN_S 14 // [46:46]
|
||||
#define CSD_2_v21_ER_BLEN_EN_M 0x01
|
||||
|
||||
#define CSD_2_v22_WP_GRP_SIZE_S 0 // [36:32]
|
||||
#define CSD_2_v22_WP_GRP_SIZE_M 0x1F
|
||||
#define CSD_2_v22_ER_GRP_SIZE_S 5 // [41:37]
|
||||
#define CSD_2_v22_ER_GRP_SIZE_M 0x1F
|
||||
#define CSD_2_v22_SECT_SIZE_S 10 // [46:42]
|
||||
#define CSD_2_v22_SECT_SIZE_M 0x1F
|
||||
|
||||
#define CSD_2_C_SIZE_M_S 15 // [49:47]
|
||||
#define CSD_2_C_SIZE_M_M 0x07
|
||||
#define CSD_2_VDD_WMAX_S 18 // [52:50]
|
||||
#define CSD_2_VDD_WMAX_M 0x07
|
||||
#define CSD_2_VDD_WMIN_S 21 // [55:53]
|
||||
#define CSD_2_VDD_WMIN_M 0x07
|
||||
#define CSD_2_RCUR_MAX_S 24 // [58:56]
|
||||
#define CSD_2_RCUR_MAX_M 0x07
|
||||
#define CSD_2_RCUR_MIN_S 27 // [61:59]
|
||||
#define CSD_2_RCUR_MIN_M 0x07
|
||||
#define CSD_2_CSIZE_L_S 30 // [63:62] <=> 2 LSB of CSIZE
|
||||
#define CSD_2_CSIZE_L_M 0x03
|
||||
|
||||
// Third Response INT <=> CSD[1] : bits 64 to 95
|
||||
#define CSD_1_CSIZE_H_S 0 // [73:64] <=> 10 MSB of CSIZE
|
||||
#define CSD_1_CSIZE_H_M 0x03FF
|
||||
// reserved 10 // [75:74]
|
||||
// reserved 0x03
|
||||
#define CSD_1_DSR_I_S 12 // [76:76]
|
||||
#define CSD_1_DSR_I_M 0x01
|
||||
#define CSD_1_RD_B_MIS_S 13 // [77:77]
|
||||
#define CSD_1_RD_B_MIS_M 0x01
|
||||
#define CSD_1_WR_B_MIS_S 14 // [78:78]
|
||||
#define CSD_1_WR_B_MIS_M 0x01
|
||||
#define CSD_1_RD_B_PAR_S 15 // [79:79]
|
||||
#define CSD_1_RD_B_PAR_M 0x01
|
||||
#define CSD_1_RD_B_LEN_S 16 // [83:80]
|
||||
#define CSD_1_RD_B_LEN_M 0x0F
|
||||
#define CSD_1_CCC_S 20 // [95:84]
|
||||
#define CSD_1_CCC_M 0x0FFF
|
||||
|
||||
// Fourth Response INT <=> CSD[0] : bits 96 to 127
|
||||
#define CSD_0_TRANS_SPEED_S 0 // [103:96]
|
||||
#define CSD_0_TRANS_SPEED_M 0xFF
|
||||
#define CSD_0_NSAC_S 8 // [111:104]
|
||||
#define CSD_0_NSAC_M 0xFF
|
||||
#define CSD_0_TAAC_S 16 // [119:112]
|
||||
#define CSD_0_TAAC_M 0xFF
|
||||
// reserved 24 // [121:120]
|
||||
// reserved 0x03
|
||||
#define CSD_0_MMC_SPEC_VERS_S 26 // [125:122] reserved for MMC compatibility
|
||||
#define CSD_0_MMC_SPEC_VERS_M 0x0F
|
||||
#define CSD_0_STRUCT_S 30 // [127:126]
|
||||
#define CSD_0_STRUCT_M 0x03
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#endif
|
@ -1,38 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
int
|
||||
p_memcmp(const char *to, const char *from, unsigned size)
|
||||
{
|
||||
while ((--size) && (*to++ == *from++))
|
||||
continue;
|
||||
|
||||
return (size || (*to != *from));
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
void
|
||||
memcpy(void *dst, const void *src, unsigned len)
|
||||
{
|
||||
const char *s = src;
|
||||
char *d = dst;
|
||||
|
||||
while (len--)
|
||||
*d++ = *s++;
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
void
|
||||
p_memset(char *buffer, char value, int size)
|
||||
{
|
||||
while (size--)
|
||||
*buffer++ = value;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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 "lib.h"
|
||||
|
||||
/*
|
||||
* .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_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);
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/*-
|
||||
* 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':
|
||||
xputchar(va_arg(ap, int));
|
||||
continue;
|
||||
case 's':
|
||||
for (s = va_arg(ap, char *); *s; s++)
|
||||
xputchar(*s);
|
||||
continue;
|
||||
case 'd': /* A lie, always prints unsigned */
|
||||
case 'u':
|
||||
u = va_arg(ap, unsigned);
|
||||
s = buf;
|
||||
do
|
||||
*s++ = '0' + u % 10U;
|
||||
while (u /= 10U);
|
||||
dumpbuf:;
|
||||
while (--s >= buf)
|
||||
xputchar(*s);
|
||||
continue;
|
||||
case 'x':
|
||||
u = va_arg(ap, unsigned);
|
||||
s = buf;
|
||||
do
|
||||
*s++ = hex[u & 0xfu];
|
||||
while (u >>= 4);
|
||||
goto dumpbuf;
|
||||
}
|
||||
}
|
||||
xputchar(c);
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
return;
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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$
|
||||
*/
|
||||
|
||||
#include "at91rm9200.h"
|
||||
#include "at91rm9200_lowlevel.h"
|
||||
#include "lib.h"
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
while (!(pUSART->US_CSR & AT91C_US_TXRDY))
|
||||
continue;
|
||||
pUSART->US_THR = (ch & 0xFF);
|
||||
}
|
||||
|
||||
void
|
||||
xputchar(int ch)
|
||||
{
|
||||
if (ch == '\n')
|
||||
putchar('\r');
|
||||
putchar(ch);
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "at91rm9200.h"
|
||||
#include "lib.h"
|
||||
|
||||
/*
|
||||
* void reset()
|
||||
*
|
||||
* Forces a reset of the system. Uses watchdog timer of '1', which
|
||||
* corresponds to 128 / SLCK seconds (SLCK is 32,768 Hz, so 128/32768 is
|
||||
* 1 / 256 ~= 5.4ms
|
||||
*/
|
||||
void
|
||||
reset(void)
|
||||
{
|
||||
// The following should effect a reset.
|
||||
AT91C_BASE_ST->ST_WDMR = 1 | AT91C_ST_RSTEN;
|
||||
AT91C_BASE_ST->ST_CR = AT91C_ST_WDRST;
|
||||
}
|
||||
|
||||
/*
|
||||
* void start_wdog()
|
||||
*
|
||||
* Starts a watchdog timer. We force the boot process to get to the point
|
||||
* it can kick the watch dog part of the ST part for the OS's driver.
|
||||
*/
|
||||
void
|
||||
start_wdog(int n)
|
||||
{
|
||||
// The following should effect a reset after N seconds.
|
||||
AT91C_BASE_ST->ST_WDMR = (n * (32768 / 128)) | AT91C_ST_RSTEN;
|
||||
AT91C_BASE_ST->ST_CR = AT91C_ST_WDRST;
|
||||
}
|
@ -1,517 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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 provide by Kwikbyte who specifically
|
||||
* disclaimed copyright on the code.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* ATMEL Microcontroller Software Support - ROUSSET -
|
||||
//*----------------------------------------------------------------------------
|
||||
//* The software is delivered "AS IS" without warranty or condition of any
|
||||
//* kind, either express, implied or statutory. This includes without
|
||||
//* limitation any warranty or condition with respect to merchantability or
|
||||
//* fitness for any particular purpose, or against the infringements of
|
||||
//* intellectual property rights of others.
|
||||
//*----------------------------------------------------------------------------
|
||||
//* File Name : main.c
|
||||
//* Object : main application written in C
|
||||
//* Creation : FB 21/11/2002
|
||||
//*
|
||||
//*----------------------------------------------------------------------------
|
||||
#include "at91rm9200.h"
|
||||
#include "lib_AT91RM9200.h"
|
||||
#include "mci_device.h"
|
||||
#include "lib.h"
|
||||
#include "sd-card.h"
|
||||
|
||||
#define AT91C_MCI_TIMEOUT 1000000 /* For AT91F_MCIDeviceWaitReady */
|
||||
#define SD_BLOCK_SIZE 512
|
||||
|
||||
//* Global Variables
|
||||
static AT91S_MciDevice MCI_Device;
|
||||
|
||||
/******************************************************************************
|
||||
**Error return codes
|
||||
******************************************************************************/
|
||||
#define MCI_UNSUPP_SIZE_ERROR 5
|
||||
#define MCI_UNSUPP_OFFSET_ERROR 6
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn MCIDeviceWaitReady
|
||||
//* \brief Wait for MCI Device ready
|
||||
//*----------------------------------------------------------------------------
|
||||
static unsigned int
|
||||
MCIDeviceWaitReady(unsigned int timeout)
|
||||
{
|
||||
volatile unsigned int status;
|
||||
int waitfor;
|
||||
|
||||
if (MCI_Device.state == AT91C_MCI_RX_SINGLE_BLOCK)
|
||||
waitfor = AT91C_MCI_RXBUFF;
|
||||
else
|
||||
waitfor = AT91C_MCI_NOTBUSY;
|
||||
do
|
||||
{
|
||||
status = AT91C_BASE_MCI->MCI_SR;
|
||||
timeout--;
|
||||
}
|
||||
while( !(status & waitfor) && (timeout>0) );
|
||||
|
||||
status = AT91C_BASE_MCI->MCI_SR;
|
||||
|
||||
// If End of Tx Buffer Empty interrupt occurred
|
||||
if (MCI_Device.state == AT91C_MCI_TX_SINGLE_BLOCK && status & AT91C_MCI_TXBUFE) {
|
||||
AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_TXBUFE;
|
||||
AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTDIS;
|
||||
MCI_Device.state = AT91C_MCI_IDLE;
|
||||
} // End of if AT91C_MCI_TXBUFF
|
||||
|
||||
// If End of Rx Buffer Full interrupt occurred
|
||||
if (MCI_Device.state == AT91C_MCI_RX_SINGLE_BLOCK && status & AT91C_MCI_RXBUFF) {
|
||||
AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_RXBUFF;
|
||||
AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTDIS;
|
||||
MCI_Device.state = AT91C_MCI_IDLE;
|
||||
} // End of if AT91C_MCI_RXBUFF
|
||||
|
||||
//printf("WaitReady returning status %x\n", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
swap(unsigned int v)
|
||||
{
|
||||
unsigned int t1;
|
||||
|
||||
__asm __volatile("eor %1, %0, %0, ror #16\n"
|
||||
"bic %1, %1, #0x00ff0000\n"
|
||||
"mov %0, %0, ror #8\n"
|
||||
"eor %0, %0, %1, lsr #8\n"
|
||||
: "+r" (v), "=r" (t1));
|
||||
|
||||
return (v);
|
||||
}
|
||||
|
||||
inline static unsigned int
|
||||
wait_ready()
|
||||
{
|
||||
int status;
|
||||
int timeout = AT91C_MCI_TIMEOUT;
|
||||
|
||||
// wait for CMDRDY Status flag to read the response
|
||||
do
|
||||
{
|
||||
status = AT91C_BASE_MCI->MCI_SR;
|
||||
} while( !(status & AT91C_MCI_CMDRDY) && (--timeout > 0) );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn MCI_SendCommand
|
||||
//* \brief Generic function to send a command to the MMC or SDCard
|
||||
//*----------------------------------------------------------------------------
|
||||
static int
|
||||
MCI_SendCommand(
|
||||
unsigned int Cmd,
|
||||
unsigned int Arg)
|
||||
{
|
||||
unsigned int error;
|
||||
unsigned int errorMask = AT91C_MCI_SR_ERROR;
|
||||
unsigned int opcode = Cmd & 0x3F;
|
||||
|
||||
//printf("SendCmd %d (%x) arg %x\n", opcode, Cmd, Arg);
|
||||
|
||||
// Don't check response CRC on ACMD41 (R3 response type).
|
||||
|
||||
if (opcode == 41)
|
||||
errorMask &= ~AT91C_MCI_RCRCE;
|
||||
|
||||
AT91C_BASE_MCI->MCI_ARGR = Arg;
|
||||
AT91C_BASE_MCI->MCI_CMDR = Cmd;
|
||||
|
||||
error = wait_ready();
|
||||
|
||||
if ((error & errorMask) != 0) {
|
||||
return (1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn MCI_GetStatus
|
||||
//* \brief Addressed card sends its status register
|
||||
//*----------------------------------------------------------------------------
|
||||
static unsigned int
|
||||
MCI_GetStatus()
|
||||
{
|
||||
if (MCI_SendCommand(SEND_STATUS_CMD, MCI_Device.RCA << 16))
|
||||
return 0;
|
||||
return (AT91C_BASE_MCI->MCI_RSPR[0]);
|
||||
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn MCI_ReadBlock
|
||||
//* \brief Start the read for a single 512-byte block
|
||||
//*----------------------------------------------------------------------------
|
||||
static int
|
||||
MCI_StartReadBlock(unsigned blknum, void *dataBuffer)
|
||||
{
|
||||
// Init Mode Register
|
||||
AT91C_BASE_MCI->MCI_MR |= ((SD_BLOCK_SIZE << 16) | AT91C_MCI_PDCMODE);
|
||||
|
||||
// (PDC) Receiver Transfer Enable
|
||||
AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS);
|
||||
AT91C_BASE_PDC_MCI->PDC_RPR = (unsigned int)dataBuffer;
|
||||
AT91C_BASE_PDC_MCI->PDC_RCR = SD_BLOCK_SIZE / 4;
|
||||
AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTEN;
|
||||
|
||||
// SDHC wants block offset, non-HC wants byte offset.
|
||||
if (!MCI_Device.IsSDHC)
|
||||
blknum *= SD_BLOCK_SIZE;
|
||||
|
||||
// Send the Read single block command
|
||||
if (MCI_SendCommand(READ_SINGLE_BLOCK_CMD, blknum)) {
|
||||
return AT91C_READ_ERROR;
|
||||
}
|
||||
MCI_Device.state = AT91C_MCI_RX_SINGLE_BLOCK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn MCI_readblocks
|
||||
//* \brief Read one or more blocks
|
||||
//*----------------------------------------------------------------------------
|
||||
int
|
||||
MCI_readblocks(char* dest, unsigned blknum, unsigned blkcount)
|
||||
{
|
||||
unsigned int status;
|
||||
unsigned int *walker;
|
||||
|
||||
if (MCI_Device.state != AT91C_MCI_IDLE) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((MCI_GetStatus() & AT91C_SR_READY_FOR_DATA) == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// As long as there is data to read
|
||||
while (blkcount)
|
||||
{
|
||||
//Do the reading
|
||||
if (MCI_StartReadBlock(blknum, dest))
|
||||
return -1;
|
||||
|
||||
// Wait MCI Device Ready
|
||||
status = MCIDeviceWaitReady(AT91C_MCI_TIMEOUT);
|
||||
if (status & AT91C_MCI_SR_ERROR)
|
||||
return 1;
|
||||
|
||||
// Fix erratum in MCI part - endian-swap all data.
|
||||
for (walker = (unsigned int *)dest;
|
||||
walker < (unsigned int *)(dest + SD_BLOCK_SIZE); walker++)
|
||||
*walker = swap(*walker);
|
||||
|
||||
// Update counters & pointers
|
||||
++blknum;
|
||||
--blkcount;
|
||||
dest += SD_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn MCI_read
|
||||
//* \brief Legacy read function, takes byte offset and length but was always
|
||||
//* used to read full blocks; interface preserved for existing boot code.
|
||||
//*----------------------------------------------------------------------------
|
||||
int
|
||||
MCI_read(char* dest, unsigned byteoffset, unsigned length)
|
||||
{
|
||||
return MCI_readblocks(dest,
|
||||
byteoffset/SD_BLOCK_SIZE, length/SD_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn MCI_SDCard_SendAppCommand
|
||||
//* \brief Specific function to send a specific command to the SDCard
|
||||
//*----------------------------------------------------------------------------
|
||||
static int
|
||||
MCI_SDCard_SendAppCommand(
|
||||
unsigned int Cmd_App,
|
||||
unsigned int Arg)
|
||||
{
|
||||
int status;
|
||||
|
||||
if ((status = MCI_SendCommand(APP_CMD, (MCI_Device.RCA << 16))) == 0)
|
||||
status = MCI_SendCommand(Cmd_App,Arg);
|
||||
return status;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn MCI_GetCSD
|
||||
//* \brief Asks to the specified card to send its CSD
|
||||
//*----------------------------------------------------------------------------
|
||||
static int
|
||||
MCI_GetCSD(unsigned int rca, unsigned int *response)
|
||||
{
|
||||
if (MCI_SendCommand(SEND_CSD_CMD, (rca << 16)))
|
||||
return 1;
|
||||
|
||||
response[0] = AT91C_BASE_MCI->MCI_RSPR[0];
|
||||
response[1] = AT91C_BASE_MCI->MCI_RSPR[1];
|
||||
response[2] = AT91C_BASE_MCI->MCI_RSPR[2];
|
||||
response[3] = AT91C_BASE_MCI->MCI_RSPR[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn MCI_SDCard_GetOCR
|
||||
//* \brief Wait for card to power up and determine whether it's SDHC or not.
|
||||
//*----------------------------------------------------------------------------
|
||||
static int
|
||||
MCI_SDCard_GetOCR()
|
||||
{
|
||||
unsigned int response;
|
||||
unsigned int arg = AT91C_MMC_HOST_VOLTAGE_RANGE;
|
||||
int timeout = AT91C_MCI_TIMEOUT;
|
||||
|
||||
// Force card to idle state.
|
||||
|
||||
MCI_SendCommand(GO_IDLE_STATE_CMD, AT91C_NO_ARGUMENT);
|
||||
|
||||
// Begin probe for SDHC by sending CMD8; only v2.0 cards respond to it.
|
||||
//
|
||||
// Arg is vvpp where vv is voltage range and pp is an arbitrary bit
|
||||
// pattern that gets echoed back in the response. The only voltage
|
||||
// ranges defined are:
|
||||
// 0x01 = 2.7 - 3.6
|
||||
// 0x02 = "reserved for low voltage" whatever that means.
|
||||
//
|
||||
// If the card fails to respond then it's not v2.0. If it responds by
|
||||
// echoing back exactly the arg we sent, then it's a v2.0 card and can
|
||||
// run at our voltage. That means that when we send the ACMD41 (in
|
||||
// MCI_SDCard_GetOCR) we can include the HCS bit to inquire about SDHC.
|
||||
|
||||
if (MCI_SendCommand(SD_SEND_IF_COND_CMD, 0x01AA) == 0) {
|
||||
MCI_Device.IsSDv2 = (AT91C_BASE_MCI->MCI_RSPR[0] == 0x01AA);
|
||||
}
|
||||
|
||||
// If we've determined the card supports v2.0 functionality, set the
|
||||
// HCS/CCS bit to indicate that we support SDHC. This will cause a
|
||||
// v2.0 card to report whether it is SDHC in the ACMD41 response.
|
||||
|
||||
if (MCI_Device.IsSDv2) {
|
||||
arg |= AT91C_CCS;
|
||||
}
|
||||
|
||||
// The RCA to be used for CMD55 in Idle state shall be the card's
|
||||
// default RCA=0x0000.
|
||||
|
||||
MCI_Device.RCA = 0x0;
|
||||
|
||||
// Repeat ACMD41 until the card comes out of power-up-busy state.
|
||||
|
||||
do {
|
||||
if (MCI_SDCard_SendAppCommand(SDCARD_APP_OP_COND_CMD, arg)) {
|
||||
return 1;
|
||||
}
|
||||
response = AT91C_BASE_MCI->MCI_RSPR[0];
|
||||
} while (!(response & AT91C_CARD_POWER_UP_DONE) && (--timeout > 0));
|
||||
|
||||
// A v2.0 card sets CCS (card capacity status) in the response if it's SDHC.
|
||||
|
||||
if (MCI_Device.IsSDv2) {
|
||||
MCI_Device.IsSDHC = ((response & AT91C_CCS) == AT91C_CCS);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn MCI_SDCard_GetCID
|
||||
//* \brief Asks to the SDCard on the chosen slot to send its CID
|
||||
//*----------------------------------------------------------------------------
|
||||
static int
|
||||
MCI_SDCard_GetCID(unsigned int *response)
|
||||
{
|
||||
if (MCI_SendCommand(ALL_SEND_CID_CMD, AT91C_NO_ARGUMENT))
|
||||
return 1;
|
||||
|
||||
response[0] = AT91C_BASE_MCI->MCI_RSPR[0];
|
||||
response[1] = AT91C_BASE_MCI->MCI_RSPR[1];
|
||||
response[2] = AT91C_BASE_MCI->MCI_RSPR[2];
|
||||
response[3] = AT91C_BASE_MCI->MCI_RSPR[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn sdcard_4wire
|
||||
//* \brief Set bus width to 1-bit or 4-bit according to the parm.
|
||||
//*
|
||||
//* Unlike most functions in this file, the return value from this one is
|
||||
//* bool-ish; returns 0 on failure, 1 on success.
|
||||
//*----------------------------------------------------------------------------
|
||||
int
|
||||
sdcard_use4wire(int use4wire)
|
||||
{
|
||||
volatile int ret_value;
|
||||
|
||||
do {
|
||||
ret_value=MCI_GetStatus();
|
||||
}
|
||||
while((ret_value > 0) && ((ret_value & AT91C_SR_READY_FOR_DATA) == 0));
|
||||
|
||||
// If going to 4-wire mode, ask the card to turn off the DAT3 card detect
|
||||
// pullup resistor, if going to 1-wire ask it to turn it back on.
|
||||
|
||||
ret_value = MCI_SDCard_SendAppCommand(SDCARD_SET_CLR_CARD_DETECT_CMD,
|
||||
use4wire ? 0 : 1);
|
||||
if (ret_value != AT91C_CMD_SEND_OK)
|
||||
return 0;
|
||||
|
||||
// Ask the card to go into the requested mode.
|
||||
|
||||
ret_value = MCI_SDCard_SendAppCommand(SDCARD_SET_BUS_WIDTH_CMD,
|
||||
use4wire ? AT91C_BUS_WIDTH_4BITS :
|
||||
AT91C_BUS_WIDTH_1BIT);
|
||||
if (ret_value != AT91C_CMD_SEND_OK)
|
||||
return 0;
|
||||
|
||||
// Set the MCI device to match the mode we set in the card.
|
||||
|
||||
if (use4wire) {
|
||||
MCI_Device.SDCard_bus_width = AT91C_BUS_WIDTH_4BITS;
|
||||
AT91C_BASE_MCI->MCI_SDCR |= AT91C_MCI_SCDBUS;
|
||||
} else {
|
||||
MCI_Device.SDCard_bus_width = AT91C_BUS_WIDTH_1BIT;
|
||||
AT91C_BASE_MCI->MCI_SDCR &= ~AT91C_MCI_SCDBUS;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn sdcard_init
|
||||
//* \brief get the mci device ready to read from an SD or SDHC card.
|
||||
//*
|
||||
//* Unlike most functions in this file, the return value from this one is
|
||||
//* bool-ish; returns 0 on failure, 1 on success.
|
||||
//*----------------------------------------------------------------------------
|
||||
int
|
||||
sdcard_init(void)
|
||||
{
|
||||
unsigned int tab_response[4];
|
||||
int i;
|
||||
|
||||
// Init MCI for MMC and SDCard interface
|
||||
AT91F_MCI_CfgPIO();
|
||||
AT91F_MCI_CfgPMC();
|
||||
AT91F_PDC_Open(AT91C_BASE_PDC_MCI);
|
||||
|
||||
// Init Device Structure
|
||||
MCI_Device.state = AT91C_MCI_IDLE;
|
||||
MCI_Device.SDCard_bus_width = 0;
|
||||
MCI_Device.IsSDv2 = 0;
|
||||
MCI_Device.IsSDHC = 0;
|
||||
|
||||
// Reset the MCI and set the bus speed.
|
||||
// Using MCK/230 gives a legal (under 400khz) bus speed for the card id
|
||||
// sequence for all reasonable master clock speeds.
|
||||
|
||||
AT91C_BASE_MCI->MCI_CR = AT91C_MCI_MCIDIS | 0x80;
|
||||
AT91C_BASE_MCI->MCI_IDR = 0xFFFFFFFF;
|
||||
AT91C_BASE_MCI->MCI_DTOR = AT91C_MCI_DTOR_1MEGA_CYCLES;
|
||||
AT91C_BASE_MCI->MCI_MR = AT91C_MCI_PDCMODE | 114; /* clkdiv 114 = MCK/230 */
|
||||
AT91C_BASE_MCI->MCI_SDCR = AT91C_MCI_MMC_SLOTA;
|
||||
AT91C_BASE_MCI->MCI_CR = AT91C_MCI_MCIEN|AT91C_MCI_PWSEN;
|
||||
|
||||
// Wait for the card to come out of power-up-busy state by repeatedly
|
||||
// sending ACMD41. This also probes for SDHC versus standard cards.
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
if (MCI_SDCard_GetOCR() == 0)
|
||||
break;
|
||||
if ((i & 0x01) == 0) {
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
if (i >= 100)
|
||||
return 0;
|
||||
|
||||
if (MCI_SDCard_GetCID(tab_response))
|
||||
return 0;
|
||||
|
||||
// Tell the card to set its address, and remember the result.
|
||||
|
||||
if (MCI_SendCommand(SET_RELATIVE_ADDR_CMD, 0))
|
||||
return 0;
|
||||
MCI_Device.RCA = (AT91C_BASE_MCI->MCI_RSPR[0] >> 16);
|
||||
|
||||
// After sending CMD3 (set addr) we can increase the clock to full speed.
|
||||
// Using MCK/4 gives a legal (under 25mhz) bus speed for all reasonable
|
||||
// master clock speeds.
|
||||
|
||||
AT91C_BASE_MCI->MCI_MR = AT91C_MCI_PDCMODE | 1; /* clkdiv 1 = MCK/4 */
|
||||
|
||||
if (MCI_GetCSD(MCI_Device.RCA,tab_response))
|
||||
return 0;
|
||||
MCI_Device.READ_BL_LEN = (tab_response[1] >> CSD_1_RD_B_LEN_S) &
|
||||
CSD_1_RD_B_LEN_M;
|
||||
|
||||
#ifdef REPORT_SIZE
|
||||
{
|
||||
unsigned int mult,blocknr;
|
||||
// compute MULT
|
||||
mult = 1 << ( ((tab_response[2] >> CSD_2_C_SIZE_M_S) &
|
||||
CSD_2_C_SIZE_M_M) + 2 );
|
||||
// compute MSB of C_SIZE
|
||||
blocknr = ((tab_response[1] >> CSD_1_CSIZE_H_S) &
|
||||
CSD_1_CSIZE_H_M) << 2;
|
||||
// compute MULT * (LSB of C-SIZE + MSB already computed + 1) = BLOCKNR
|
||||
blocknr = mult * ((blocknr + ((tab_response[2] >> CSD_2_CSIZE_L_S) &
|
||||
CSD_2_CSIZE_L_M)) + 1);
|
||||
MCI_Device.Memory_Capacity = (1 << MCI_Device.READ_BL_LEN) * blocknr;
|
||||
printf("Found SD card %u bytes\n", MCI_Device.Memory_Capacity);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Select card and set block length for following transfers.
|
||||
|
||||
if (MCI_SendCommand(SEL_DESEL_CARD_CMD, (MCI_Device.RCA)<<16))
|
||||
return 0;
|
||||
if (MCI_SendCommand(SET_BLOCKLEN_CMD, SD_BLOCK_SIZE))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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 provide by Kwikbyte who specifically
|
||||
* disclaimed copyright on the code.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __SD_CARD_H
|
||||
#define __SD_CARD_H
|
||||
|
||||
/* MCI_read() is the original read function, taking a byte offset and byte
|
||||
* count. It is preserved to support existing customized boot code that still
|
||||
* refers to it; it will work fine even on SDHC cards as long as the kernel and
|
||||
* the metadata for locating it all exist within the first 4GB of the card.
|
||||
*
|
||||
* MCI_readblocks() is the new read function, taking offset and length in terms
|
||||
* of block counts (where the SD spec defines a block as 512 bytes), allowing
|
||||
* the kernel and filesystem metadata to be located anywhere on an SDHC card.
|
||||
*
|
||||
* Returns 0 on success, non-zero on failure.
|
||||
*/
|
||||
|
||||
int MCI_read (char* dest, unsigned bytenum, unsigned length);
|
||||
int MCI_readblocks (char* dest, unsigned blknum, unsigned blkcount);
|
||||
|
||||
/* sdcard_init() - get things set up to read from an SD or SDHC card.
|
||||
*
|
||||
* Returns 0 on failure, non-zero on success.
|
||||
*/
|
||||
|
||||
int sdcard_init(void);
|
||||
|
||||
/* By default sdcard_init() sets things up for a 1-wire interface to the
|
||||
* SD card. Calling sdcard_4wire(true) after sdcard_init() allows customized
|
||||
* boot code to change to 4-bit transfers when the hardware supports it.
|
||||
*
|
||||
* Returns 0 on failure, non-zero on success.
|
||||
*/
|
||||
int sdcard_use4wire(int use4wire);
|
||||
|
||||
#endif
|
||||
|
@ -1,267 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Filename: spi_flash.c
|
||||
*
|
||||
* Instantiation of SPI flash control routines supporting AT45DB161B
|
||||
*
|
||||
* Revision information:
|
||||
*
|
||||
* 17JAN2005 kb_admin initial creation
|
||||
* adapted from external sources
|
||||
* tested for basic operation only!!!
|
||||
*
|
||||
* 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 "spi_flash.h"
|
||||
#include "lib.h"
|
||||
|
||||
/*********************** PRIVATE FUNCTIONS/DATA ******************************/
|
||||
|
||||
|
||||
static spiCommand_t spi_command;
|
||||
static char tx_commandBuffer[8], rx_commandBuffer[8];
|
||||
|
||||
/*
|
||||
* .KB_C_FN_DEFINITION_START
|
||||
* void SendCommand(spiCommand_t *pCommand)
|
||||
* Private function sends 8-bit value to the device and returns the 8-bit
|
||||
* value in response.
|
||||
* .KB_C_FN_DEFINITION_END
|
||||
*/
|
||||
static void
|
||||
SendCommand(spiCommand_t *pCommand)
|
||||
{
|
||||
AT91PS_SPI pSPI = AT91C_BASE_SPI;
|
||||
|
||||
pSPI->SPI_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
|
||||
|
||||
pSPI->SPI_RPR = (unsigned)pCommand->rx_cmd;
|
||||
pSPI->SPI_RCR = pCommand->rx_cmd_size;
|
||||
pSPI->SPI_TPR = (unsigned)pCommand->tx_cmd;
|
||||
pSPI->SPI_TCR = pCommand->tx_cmd_size;
|
||||
|
||||
pSPI->SPI_TNPR = (unsigned)pCommand->tx_data;
|
||||
pSPI->SPI_TNCR = pCommand->tx_data_size;
|
||||
pSPI->SPI_RNPR = (unsigned)pCommand->rx_data;
|
||||
pSPI->SPI_RNCR = pCommand->rx_data_size;
|
||||
|
||||
pSPI->SPI_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
|
||||
|
||||
// wait for completion
|
||||
while (!(pSPI->SPI_SR & AT91C_SPI_SPENDRX))
|
||||
Delay(700);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .KB_C_FN_DEFINITION_START
|
||||
* char GetFlashStatus(void)
|
||||
* Private function to return device status.
|
||||
* .KB_C_FN_DEFINITION_END
|
||||
*/
|
||||
static char
|
||||
GetFlashStatus(void)
|
||||
{
|
||||
p_memset((char *)&spi_command, 0, sizeof(spi_command));
|
||||
p_memset(tx_commandBuffer, 0, 8);
|
||||
tx_commandBuffer[0] = STATUS_REGISTER_READ;
|
||||
p_memset(rx_commandBuffer, 0, 8);
|
||||
spi_command.tx_cmd = tx_commandBuffer;
|
||||
spi_command.rx_cmd = rx_commandBuffer;
|
||||
spi_command.rx_cmd_size = 2;
|
||||
spi_command.tx_cmd_size = 2;
|
||||
SendCommand(&spi_command);
|
||||
return (rx_commandBuffer[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* .KB_C_FN_DEFINITION_START
|
||||
* void WaitForDeviceReady(void)
|
||||
* Private function to poll until the device is ready for next operation.
|
||||
* .KB_C_FN_DEFINITION_END
|
||||
*/
|
||||
static void
|
||||
WaitForDeviceReady(void)
|
||||
{
|
||||
while (!(GetFlashStatus() & 0x80)) ;
|
||||
}
|
||||
|
||||
/*************************** GLOBAL FUNCTIONS ********************************/
|
||||
|
||||
|
||||
/*
|
||||
* .KB_C_FN_DEFINITION_START
|
||||
* void SPI_ReadFlash(unsigned flash_addr, unsigned dest_addr, unsigned size)
|
||||
* Global function to read the SPI flash device using the continuous read
|
||||
* array command.
|
||||
* .KB_C_FN_DEFINITION_END
|
||||
*/
|
||||
void
|
||||
SPI_ReadFlash(unsigned flash_addr, char *dest_addr, unsigned size)
|
||||
{
|
||||
unsigned pageAddress, byteAddress;
|
||||
|
||||
// determine page address
|
||||
pageAddress = flash_addr / FLASH_PAGE_SIZE;
|
||||
|
||||
// determine byte address
|
||||
byteAddress = flash_addr % FLASH_PAGE_SIZE;
|
||||
|
||||
p_memset(tx_commandBuffer, 0, 8);
|
||||
#ifdef BOOT_BWCT
|
||||
tx_commandBuffer[0] = 0xd2;
|
||||
tx_commandBuffer[1] = ((pageAddress >> 6) & 0xFF);
|
||||
tx_commandBuffer[2] = ((pageAddress << 2) & 0xFC) |
|
||||
((byteAddress >> 8) & 0x3);
|
||||
tx_commandBuffer[3] = byteAddress & 0xFF;
|
||||
spi_command.tx_cmd = tx_commandBuffer;
|
||||
spi_command.tx_cmd_size = 8;
|
||||
spi_command.tx_data_size = size;
|
||||
spi_command.tx_data = dest_addr;
|
||||
|
||||
p_memset(rx_commandBuffer, 0, 8);
|
||||
spi_command.rx_cmd = rx_commandBuffer;
|
||||
spi_command.rx_cmd_size = 8;
|
||||
spi_command.rx_data_size = size;
|
||||
spi_command.rx_data = dest_addr;
|
||||
#else
|
||||
tx_commandBuffer[0] = CONTINUOUS_ARRAY_READ_HF;
|
||||
tx_commandBuffer[1] = ((pageAddress >> 5) & 0xFF);
|
||||
tx_commandBuffer[2] = ((pageAddress << 3) & 0xF8) |
|
||||
((byteAddress >> 8) & 0x7);
|
||||
tx_commandBuffer[3] = byteAddress & 0xFF;
|
||||
spi_command.tx_cmd = tx_commandBuffer;
|
||||
spi_command.tx_cmd_size = 5;
|
||||
spi_command.tx_data_size = size;
|
||||
spi_command.tx_data = dest_addr;
|
||||
|
||||
p_memset(rx_commandBuffer, 0, 8);
|
||||
spi_command.rx_cmd = rx_commandBuffer;
|
||||
spi_command.rx_cmd_size = 5;
|
||||
spi_command.rx_data_size = size;
|
||||
spi_command.rx_data = dest_addr;
|
||||
#endif
|
||||
|
||||
SendCommand(&spi_command);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* .KB_C_FN_DEFINITION_START
|
||||
* void SPI_WriteFlash(unsigned flash_addr, unsigned src_addr, unsigned size)
|
||||
* Global function to program the SPI flash device. Notice the warning
|
||||
* provided in lower-level functions regarding corruption of data in non-
|
||||
* page aligned write operations.
|
||||
* .KB_C_FN_DEFINITION_END
|
||||
*/
|
||||
void
|
||||
SPI_WriteFlash(unsigned flash_addr, char *src_addr, unsigned size)
|
||||
{
|
||||
unsigned pageAddress, byteAddress;
|
||||
|
||||
// determine page address
|
||||
pageAddress = flash_addr / FLASH_PAGE_SIZE;
|
||||
|
||||
// determine byte address
|
||||
byteAddress = flash_addr % FLASH_PAGE_SIZE;
|
||||
|
||||
p_memset(tx_commandBuffer, 0, 8);
|
||||
#ifdef BOOT_BWCT
|
||||
tx_commandBuffer[0] = 0x82;
|
||||
tx_commandBuffer[1] = ((pageAddress >> 6) & 0xFF);
|
||||
tx_commandBuffer[2] = ((pageAddress << 2) & 0xFC) |
|
||||
((byteAddress >> 8) & 0x3);
|
||||
tx_commandBuffer[3] = (byteAddress & 0xFF);
|
||||
#else
|
||||
tx_commandBuffer[0] = PROGRAM_THROUGH_BUFFER;
|
||||
tx_commandBuffer[1] = ((pageAddress >> 5) & 0xFF);
|
||||
tx_commandBuffer[2] = ((pageAddress << 3) & 0xF8) |
|
||||
((byteAddress >> 8) & 0x7);
|
||||
tx_commandBuffer[3] = (byteAddress & 0xFF);
|
||||
#endif
|
||||
|
||||
p_memset(rx_commandBuffer, 0, 8);
|
||||
|
||||
spi_command.tx_cmd = tx_commandBuffer;
|
||||
spi_command.rx_cmd = rx_commandBuffer;
|
||||
spi_command.rx_cmd_size = 4;
|
||||
spi_command.tx_cmd_size = 4;
|
||||
|
||||
spi_command.tx_data_size = size;
|
||||
spi_command.tx_data = src_addr;
|
||||
spi_command.rx_data_size = size;
|
||||
spi_command.rx_data = src_addr;
|
||||
|
||||
SendCommand(&spi_command);
|
||||
|
||||
WaitForDeviceReady();
|
||||
}
|
||||
|
||||
/*
|
||||
* .KB_C_FN_DEFINITION_START
|
||||
* void SPI_InitFlash(void)
|
||||
* Global function to initialize the SPI flash device/accessor functions.
|
||||
* .KB_C_FN_DEFINITION_END
|
||||
*/
|
||||
void
|
||||
SPI_InitFlash(void)
|
||||
{
|
||||
AT91PS_PIO pPio;
|
||||
AT91PS_SPI pSPI = AT91C_BASE_SPI;
|
||||
unsigned value;
|
||||
|
||||
// enable CS0, CLK, MOSI, MISO
|
||||
pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
|
||||
pPio->PIO_ASR = AT91C_PIO_PA3 | AT91C_PIO_PA1 | AT91C_PIO_PA0 |
|
||||
AT91C_PIO_PA2;
|
||||
pPio->PIO_PDR = AT91C_PIO_PA3 | AT91C_PIO_PA1 | AT91C_PIO_PA0 |
|
||||
AT91C_PIO_PA2;
|
||||
|
||||
// enable clocks to SPI
|
||||
AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_SPI;
|
||||
|
||||
// reset the SPI
|
||||
pSPI->SPI_CR = AT91C_SPI_SWRST;
|
||||
|
||||
pSPI->SPI_MR = (0xf << 24) | AT91C_SPI_MSTR | AT91C_SPI_MODFDIS |
|
||||
(0xE << 16);
|
||||
|
||||
pSPI->SPI_CSR[0] = AT91C_SPI_CPOL | (4 << 16) | (2 << 8);
|
||||
pSPI->SPI_CR = AT91C_SPI_SPIEN;
|
||||
|
||||
pSPI->SPI_PTCR = AT91C_PDC_TXTDIS;
|
||||
pSPI->SPI_PTCR = AT91C_PDC_RXTDIS;
|
||||
pSPI->SPI_RNPR = 0;
|
||||
pSPI->SPI_RNCR = 0;
|
||||
pSPI->SPI_TNPR = 0;
|
||||
pSPI->SPI_TNCR = 0;
|
||||
pSPI->SPI_RPR = 0;
|
||||
pSPI->SPI_RCR = 0;
|
||||
pSPI->SPI_TPR = 0;
|
||||
pSPI->SPI_TCR = 0;
|
||||
pSPI->SPI_PTCR = AT91C_PDC_RXTEN;
|
||||
pSPI->SPI_PTCR = AT91C_PDC_TXTEN;
|
||||
|
||||
value = pSPI->SPI_RDR;
|
||||
value = pSPI->SPI_SR;
|
||||
|
||||
value = GetFlashStatus() & 0xFC;
|
||||
#ifdef BOOT_BWCT
|
||||
if (value != 0xB4 && value != 0xAC)
|
||||
printf(" Bad SPI status: 0x%x\n", value);
|
||||
#else
|
||||
if (value != 0xBC)
|
||||
printf(" Bad SPI status: 0x%x\n", value);
|
||||
#endif
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Filename: spi_flash.h
|
||||
*
|
||||
* Definition of flash control routines supporting AT45DB161B
|
||||
*
|
||||
* Revision information:
|
||||
*
|
||||
* 17JAN2005 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 _SPI_FLASH_H_
|
||||
#define _SPI_FLASH_H_
|
||||
|
||||
typedef struct {
|
||||
char *tx_cmd;
|
||||
unsigned tx_cmd_size;
|
||||
char *rx_cmd;
|
||||
unsigned rx_cmd_size;
|
||||
char *tx_data;
|
||||
unsigned tx_data_size;
|
||||
char *rx_data;
|
||||
unsigned rx_data_size;
|
||||
} spiCommand_t;
|
||||
|
||||
void SPI_ReadFlash(unsigned flash_addr, char *dest_addr, unsigned size);
|
||||
void SPI_WriteFlash(unsigned flash_addr, char *dest_addr, unsigned size);
|
||||
void SPI_InitFlash(void);
|
||||
|
||||
void SPI_GetId(unsigned *id);
|
||||
|
||||
#ifdef BOOT_BWCT
|
||||
#define FLASH_PAGE_SIZE 528
|
||||
#else
|
||||
#define FLASH_PAGE_SIZE 1056
|
||||
#endif
|
||||
|
||||
// Flash commands
|
||||
|
||||
#define CONTINUOUS_ARRAY_READ 0xE8
|
||||
#define CONTINUOUS_ARRAY_READ_HF 0x0B
|
||||
#define CONTINUOUS_ARRAY_READ_LF 0x03
|
||||
#define STATUS_REGISTER_READ 0xD7
|
||||
#define PROGRAM_THROUGH_BUFFER 0x82
|
||||
#define MANUFACTURER_ID 0x9F
|
||||
|
||||
#endif
|
@ -1,36 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
int
|
||||
strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
for (; *s1 == *s2 && *s1; s1++, s2++);
|
||||
return (unsigned char)*s1 - (unsigned char)*s2;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
char *
|
||||
strcpy(char *to, const char *from)
|
||||
{
|
||||
while (*from)
|
||||
*to++ = *from++;
|
||||
*to++ = '\0';
|
||||
return (to);
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
*****************************************************************************/
|
||||
|
||||
#include "lib.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
|
||||
* 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);
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
*****************************************************************************/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
/*
|
||||
* .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)
|
||||
{
|
||||
const char *ptr = buffer;
|
||||
while (*ptr++)
|
||||
continue;
|
||||
return (ptr - buffer - 1);
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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"
|
||||
#include <linux/asm/setup.h>
|
||||
#include "tag_list.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;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 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_ */
|
@ -1,128 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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 provide by Kwikbyte who specifically
|
||||
* disclaimed copyright on the code. This version of xmodem has been nearly
|
||||
* completely rewritten, but the CRC is from the original.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
#define PACKET_SIZE 128
|
||||
|
||||
/* Line control codes */
|
||||
#define SOH 0x01 /* start of header */
|
||||
#define ACK 0x06 /* Acknowledge */
|
||||
#define NAK 0x15 /* Negative acknowledge */
|
||||
#define CAN 0x18 /* Cancel */
|
||||
#define EOT 0x04 /* end of text */
|
||||
|
||||
#define TO 10
|
||||
/*
|
||||
* int GetRecord(char , char *)
|
||||
* This private function receives a x-modem record to the pointer and
|
||||
* returns non-zero on success.
|
||||
*/
|
||||
static int
|
||||
GetRecord(char blocknum, char *dest)
|
||||
{
|
||||
int size;
|
||||
int ch;
|
||||
unsigned chk, j;
|
||||
|
||||
chk = 0;
|
||||
|
||||
if ((ch = getc(TO)) == -1)
|
||||
goto err;
|
||||
if (ch != blocknum)
|
||||
goto err;
|
||||
if ((ch = getc(TO)) == -1)
|
||||
goto err;
|
||||
if (ch != (~blocknum & 0xff))
|
||||
goto err;
|
||||
|
||||
for (size = 0; size < PACKET_SIZE; ++size) {
|
||||
if ((ch = getc(TO)) == -1)
|
||||
goto err;
|
||||
chk = chk ^ ch << 8;
|
||||
for (j = 0; j < 8; ++j) {
|
||||
if (chk & 0x8000)
|
||||
chk = chk << 1 ^ 0x1021;
|
||||
else
|
||||
chk = chk << 1;
|
||||
}
|
||||
*dest++ = ch;
|
||||
}
|
||||
|
||||
chk &= 0xFFFF;
|
||||
|
||||
if (((ch = getc(TO)) == -1) || ((ch & 0xff) != ((chk >> 8) & 0xFF)))
|
||||
goto err;
|
||||
if (((ch = getc(TO)) == -1) || ((ch & 0xff) != (chk & 0xFF)))
|
||||
goto err;
|
||||
putchar(ACK);
|
||||
|
||||
return (1);
|
||||
err:;
|
||||
putchar(CAN);
|
||||
// We should allow for resend, but we don't.
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* int xmodem_rx(char *)
|
||||
* This global function receives a x-modem transmission consisting of
|
||||
* (potentially) several blocks. Returns the number of bytes received or
|
||||
* -1 on error.
|
||||
*/
|
||||
int
|
||||
xmodem_rx(char *dest)
|
||||
{
|
||||
int starting, ch;
|
||||
char packetNumber, *startAddress = dest;
|
||||
|
||||
packetNumber = 1;
|
||||
starting = 1;
|
||||
|
||||
while (1) {
|
||||
if (starting)
|
||||
putchar('C');
|
||||
if (((ch = getc(1)) == -1) || (ch != SOH && ch != EOT))
|
||||
continue;
|
||||
if (ch == EOT) {
|
||||
putchar(ACK);
|
||||
return (dest - startAddress);
|
||||
}
|
||||
starting = 0;
|
||||
// Xmodem packets: SOH PKT# ~PKT# 128-bytes CRC16
|
||||
if (!GetRecord(packetNumber, dest))
|
||||
return (-1);
|
||||
dest += PACKET_SIZE;
|
||||
packetNumber++;
|
||||
}
|
||||
|
||||
// the loop above should return in all cases
|
||||
return (-1);
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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)
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = 0;
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
}
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
.data :
|
||||
{
|
||||
__data_start = . ;
|
||||
*(.data)
|
||||
}
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
__bss_start = .;
|
||||
__bss_start__ = .;
|
||||
.bss :
|
||||
{
|
||||
*(.bss)
|
||||
. = ALIGN(32 / 8);
|
||||
}
|
||||
. = ALIGN(32 / 8);
|
||||
_end = .;
|
||||
_bss_end__ = . ; __bss_end__ = . ; __end__ = . ;
|
||||
PROVIDE (end = .);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.if !target(__ixp425_boot_Makefile.inc__)
|
||||
.PATH: ${.CURDIR}/../../../../libkern ${.CURDIR}/../../../../libkern/arm
|
||||
|
||||
__ixp425_boot_Makefile.inc__:
|
||||
|
||||
# Both Avila and Pronghorn Metro are supported by ixp425
|
||||
BOOT_FLAVOR=ixp425
|
||||
|
||||
CFLAGS+=-Os -ffreestanding \
|
||||
-I${.CURDIR}/../../../.. \
|
||||
-I${.CURDIR}/../../../../arm \
|
||||
-DCPU_XSCALE_IXP425 \
|
||||
-Wall -Waggregate-return \
|
||||
-Werror \
|
||||
-Wnested-externs \
|
||||
-Wpointer-arith -Wshadow -Wwrite-strings \
|
||||
-Wmissing-prototypes \
|
||||
-Wmissing-declarations
|
||||
|
||||
# -Wstrict-prototypes
|
||||
|
||||
CFLAGS+=-DBOOT_${BOOT_FLAVOR:tu}
|
||||
|
||||
LD ?= ld
|
||||
OBJCOPY ?= objcopy
|
||||
|
||||
.if defined(P)
|
||||
${P}: ${OBJS}
|
||||
${LD} ${LDFLAGS} -o ${.TARGET} ${OBJS}
|
||||
|
||||
CLEANFILES+= ${P}
|
||||
.endif
|
||||
|
||||
.if defined(WITH_TAG_LIST)
|
||||
MK_TAG_LIST:=yes
|
||||
.else
|
||||
MK_TAG_LIST:=no
|
||||
.endif
|
||||
|
||||
.endif
|
@ -1,78 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
||||
# We get a lot of the std lib functions from here.
|
||||
.PATH: ${.CURDIR}/../../at91/libat91
|
||||
|
||||
# Enable to get debug msgs
|
||||
#DEBUG=yes
|
||||
|
||||
# Hack to search through the kernel for ufs:ad0s1a and replace it with
|
||||
# the correct one for the active slice/partition.
|
||||
FIXUP_BOOT_DRV=yes
|
||||
|
||||
P=boot2
|
||||
FILES=${P}
|
||||
SRCS=arm_init.S boot2.c ${BOOT_FLAVOR:tl}_board.c
|
||||
SRCS+=memchr.c memcmp.c memcpy.c memmem.c memset.c printf.c strcmp.c strcpy.c
|
||||
SRCS+=strlen.c ashldi3.c divsi3.S muldi3.c
|
||||
SRCS+=aeabi_unwind.c
|
||||
MAN=
|
||||
|
||||
KERNPHYSADDR=0x180000
|
||||
KERNVIRTADDR=${KERNPHYSADDR}
|
||||
BOOT_STACK=0x200000-4
|
||||
M=${MACHINE}
|
||||
LDFLAGS=-e ${KERNPHYSADDR} -EB -T ldscript.${M}
|
||||
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
|
||||
S=${.CURDIR}/../../../..
|
||||
|
||||
CFLAGS+= \
|
||||
-DBOOT_STACK=${BOOT_STACK} \
|
||||
-I${.CURDIR}/../../../common \
|
||||
-I${.CURDIR}
|
||||
|
||||
.if defined(FIXUP_BOOT_DRV)
|
||||
CFLAGS+=-DFIXUP_BOOT_DRV
|
||||
.endif
|
||||
.if defined(DEBUG)
|
||||
CFLAGS+=-DDEBUG
|
||||
.endif
|
||||
|
||||
ldscript.$M: $S/conf/ldscript.$M
|
||||
cat $S/conf/ldscript.$M|sed s/KERNPHYSADDR/${KERNPHYSADDR}/g| \
|
||||
sed s/KERNVIRTADDR/${KERNVIRTADDR}/g | \
|
||||
sed s/" + SIZEOF_HEADERS"// > ldscript.$M
|
||||
|
||||
${P}: ldscript.$M
|
||||
|
||||
CLEANFILES+=ldscript.$M
|
||||
|
||||
memchr.c: $S/../lib/libc/string/memchr.c
|
||||
sed -e 's/string\.h/lib.h/' < $S/../lib/libc/string/memchr.c > \
|
||||
${.TARGET}
|
||||
|
||||
memmem.c: $S/../lib/libc/string/memmem.c
|
||||
sed -e 's/string\.h/lib.h/' < $S/../lib/libc/string/memmem.c > \
|
||||
${.TARGET}
|
||||
|
||||
CLEANFILES+=memchr.c memmem.c
|
||||
|
||||
ashldi3.o: $S/libkern/ashldi3.c
|
||||
${CC} -c ${CFLAGS} -D_KERNEL -o ${.TARGET} ${.IMPSRC}
|
||||
|
||||
divsi3.o: $S/libkern/${M}/divsi3.S
|
||||
${CC} -c ${CFLAGS} -D_KERNEL -o ${.TARGET} ${.IMPSRC}
|
||||
|
||||
muldi3.o: $S/libkern/${M}/muldi3.c
|
||||
${CC} -c ${CFLAGS} -D_KERNEL -o ${.TARGET} ${.IMPSRC}
|
||||
|
||||
inflate.c: $S/kern/inflate.c
|
||||
sed -e 's/extern void putstr (char/extern void putstr (const char/' < \
|
||||
$S/kern/inflate.c > ${.TARGET}
|
||||
|
||||
CLEANFILES+=inflate.c
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -1,58 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 John Hay. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
|
||||
ASENTRY_NP(start)
|
||||
/* Initialise bss and sp */
|
||||
nop
|
||||
adr r1, .Lstart
|
||||
ldmia r1, {r1, r2, sp} /* Set initial stack and */
|
||||
sub r2, r2, r1 /* get zero init data */
|
||||
mov r3, #0
|
||||
.L1:
|
||||
str r3, [r1], #0x0004 /* get zero init data */
|
||||
subs r2, r2, #4
|
||||
bgt .L1
|
||||
|
||||
.extern main
|
||||
bl main
|
||||
/* main should not return. If it does, spin forever */
|
||||
infiniteLoop:
|
||||
b infiniteLoop
|
||||
END(start)
|
||||
|
||||
.Lstart:
|
||||
.word _edata
|
||||
.word _end
|
||||
.word BOOT_STACK
|
||||
|
||||
ENTRY(cpu_id)
|
||||
mrc p15, 0, r0, c0, c0, 0
|
||||
RET
|
||||
END(cpu_id)
|
||||
|
||||
/* End */
|
@ -1,446 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 John Hay
|
||||
* Copyright (c) 1998 Robert Nordier
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/diskmbr.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/reboot.h>
|
||||
|
||||
#include <machine/elf.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "paths.h"
|
||||
#include "rbx.h"
|
||||
|
||||
extern uint32_t _end;
|
||||
|
||||
#define NOPT 6
|
||||
|
||||
static const char optstr[NOPT] = "agnrsv";
|
||||
static const unsigned char flags[NOPT] = {
|
||||
RBX_ASKNAME,
|
||||
RBX_GDB,
|
||||
RBX_NOINTR,
|
||||
RBX_DFLTROOT,
|
||||
RBX_SINGLE,
|
||||
RBX_VERBOSE
|
||||
};
|
||||
|
||||
static unsigned dsk_start;
|
||||
static char cmd[512];
|
||||
static char kname[1024];
|
||||
static uint32_t opts;
|
||||
static uint8_t dsk_meta;
|
||||
static int bootslice;
|
||||
static int bootpart;
|
||||
static int disk_layout;
|
||||
#define DL_UNKNOWN 0
|
||||
#define DL_RAW 1 /* Dangerously dedicated */
|
||||
#define DL_SLICE 2 /* Use only slices (DOS partitions) */
|
||||
#define DL_SLICEPART 3 /* Use slices and partitions */
|
||||
|
||||
static void load(void);
|
||||
static int parse(void);
|
||||
static int dskread(void *, unsigned, unsigned);
|
||||
static int drvread(void *, unsigned, unsigned);
|
||||
#ifdef FIXUP_BOOT_DRV
|
||||
static void fixup_boot_drv(caddr_t, int, int, int);
|
||||
#endif
|
||||
|
||||
#include "ufsread.c"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
|
||||
{
|
||||
if ((size_t)fsread(inode, buf, nbyte) != nbyte)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
getstr(int c)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = cmd;
|
||||
if (c == 0)
|
||||
c = getc(10000);
|
||||
for (;;) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
break;
|
||||
case '\177':
|
||||
case '\b':
|
||||
if (s > cmd) {
|
||||
s--;
|
||||
printf("\b \b");
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
*s = 0;
|
||||
return;
|
||||
default:
|
||||
if (s - cmd < sizeof(cmd) - 1)
|
||||
*s++ = c;
|
||||
xputchar(c);
|
||||
}
|
||||
c = getc(10000);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const char *bt;
|
||||
int autoboot, c = 0;
|
||||
ufs_ino_t ino;
|
||||
|
||||
dmadat = (void *)(0x1c0000);
|
||||
p_memset((char *)dmadat, 0, 32 * 1024);
|
||||
bt = board_init();
|
||||
|
||||
printf("FreeBSD ARM (%s) boot2 v%d.%d\n", bt, 0, 4);
|
||||
|
||||
autoboot = 1;
|
||||
|
||||
/* Process configuration file */
|
||||
if ((ino = lookup(PATH_CONFIG)) ||
|
||||
(ino = lookup(PATH_DOTCONFIG)))
|
||||
fsread(ino, cmd, sizeof(cmd));
|
||||
|
||||
if (*cmd) {
|
||||
if (parse())
|
||||
autoboot = 0;
|
||||
printf("%s: %s\n", PATH_CONFIG, cmd);
|
||||
/* Do not process this command twice */
|
||||
*cmd = 0;
|
||||
}
|
||||
|
||||
if (*kname == '\0')
|
||||
strcpy(kname, PATH_KERNEL);
|
||||
|
||||
/* Present the user with the boot2 prompt. */
|
||||
for (;;) {
|
||||
printf("\nDefault: %s\nboot: ", kname);
|
||||
if (!autoboot ||
|
||||
(OPT_CHECK(RBX_NOINTR) == 0 && (c = getc(2)) != 0))
|
||||
getstr(c);
|
||||
xputchar('\n');
|
||||
autoboot = 0;
|
||||
c = 0;
|
||||
DPRINTF("cmd is '%s'\n", cmd);
|
||||
if (parse())
|
||||
xputchar('\a');
|
||||
else
|
||||
load();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
load(void)
|
||||
{
|
||||
Elf32_Ehdr eh;
|
||||
static Elf32_Phdr ep[2];
|
||||
caddr_t p;
|
||||
ufs_ino_t ino;
|
||||
uint32_t addr;
|
||||
int i, j;
|
||||
#ifdef FIXUP_BOOT_DRV
|
||||
caddr_t staddr;
|
||||
int klen;
|
||||
|
||||
staddr = (caddr_t)0xffffffff;
|
||||
klen = 0;
|
||||
#endif
|
||||
if (!(ino = lookup(kname))) {
|
||||
if (!ls)
|
||||
printf("No %s\n", kname);
|
||||
return;
|
||||
}
|
||||
DPRINTF("Found %s\n", kname);
|
||||
if (xfsread(ino, &eh, sizeof(eh)))
|
||||
return;
|
||||
if (!IS_ELF(eh)) {
|
||||
printf("Invalid %s\n", "format");
|
||||
return;
|
||||
}
|
||||
fs_off = eh.e_phoff;
|
||||
for (j = i = 0; i < eh.e_phnum && j < 2; i++) {
|
||||
if (xfsread(ino, ep + j, sizeof(ep[0])))
|
||||
return;
|
||||
if (ep[j].p_type == PT_LOAD)
|
||||
j++;
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
p = (caddr_t)(ep[i].p_paddr & 0x0fffffff);
|
||||
fs_off = ep[i].p_offset;
|
||||
#ifdef FIXUP_BOOT_DRV
|
||||
if (staddr == (caddr_t)0xffffffff)
|
||||
staddr = p;
|
||||
klen += ep[i].p_filesz;
|
||||
#endif
|
||||
if (xfsread(ino, p, ep[i].p_filesz))
|
||||
return;
|
||||
}
|
||||
addr = eh.e_entry & 0x0fffffff;
|
||||
DPRINTF("Entry point %x for %s\n", addr, kname);
|
||||
clr_board();
|
||||
#ifdef FIXUP_BOOT_DRV
|
||||
fixup_boot_drv(staddr, klen, bootslice, bootpart);
|
||||
#endif
|
||||
((void(*)(int))addr)(RB_BOOTINFO /* XXX | (opts & RBX_MASK) */);
|
||||
}
|
||||
|
||||
static int
|
||||
parse()
|
||||
{
|
||||
char *arg = cmd;
|
||||
char *ep, *p;
|
||||
int c, i;
|
||||
|
||||
while ((c = *arg++)) {
|
||||
if (c == ' ' || c == '\t' || c == '\n')
|
||||
continue;
|
||||
for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
|
||||
ep = p;
|
||||
if (*p)
|
||||
*p++ = 0;
|
||||
if (c == '-') {
|
||||
while ((c = *arg++)) {
|
||||
for (i = 0; c != optstr[i]; i++)
|
||||
if (i == NOPT - 1)
|
||||
return -1;
|
||||
opts ^= OPT_SET(flags[i]);
|
||||
}
|
||||
} else {
|
||||
arg--;
|
||||
/* look for ad0s1a:... | ad0s1:... */
|
||||
if (strlen(arg) > 6 && arg[0] == 'a' &&
|
||||
arg[1] == 'd' && arg[3] == 's' &&
|
||||
(arg[5] == ':' || arg[6] == ':')) {
|
||||
/* XXX Should also handle disk. */
|
||||
bootslice = arg[4] - '0';
|
||||
if (bootslice < 1 || bootslice > 4)
|
||||
return (-1);
|
||||
bootpart = 0;
|
||||
if (arg[5] != ':')
|
||||
bootpart = arg[5] - 'a';
|
||||
if (bootpart < 0 || bootpart > 7)
|
||||
return (-1);
|
||||
dsk_meta = 0;
|
||||
if (arg[5] == ':')
|
||||
arg += 6;
|
||||
else
|
||||
arg += 7;
|
||||
/* look for ad0a:... */
|
||||
} else if (strlen(arg) > 4 && arg[0] == 'a' &&
|
||||
arg[1] == 'd' && arg[2] == '0' && arg[4] == ':') {
|
||||
bootslice = 0;
|
||||
bootpart = arg[3] - 'a';
|
||||
if (bootpart < 0 || bootpart > 7)
|
||||
return (-1);
|
||||
dsk_meta = 0;
|
||||
arg += 5;
|
||||
}
|
||||
if ((i = ep - arg)) {
|
||||
if ((size_t)i >= sizeof(kname))
|
||||
return -1;
|
||||
memcpy(kname, arg, i + 1);
|
||||
}
|
||||
}
|
||||
arg = p;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* dskread() will try to handle the disk layouts that are typically
|
||||
* encountered.
|
||||
* - raw or "Dangerously Dedicated" mode. No real slice table, just the
|
||||
* default one that is included with bsdlabel -B. Typically this is
|
||||
* used with ROOTDEVNAME=\"ufs:ad0a\".
|
||||
* - slice only. Only a slice table is installed with no bsd label or
|
||||
* bsd partition table. This is typically used with
|
||||
* ROOTDEVNAME=\"ufs:ad0s1\".
|
||||
* - slice + bsd label + partition table. This is typically done with
|
||||
* with fdisk + bsdlabel and is used with ROOTDEVNAME=\"ufs:ad0s1a\".
|
||||
*/
|
||||
static int
|
||||
dskread(void *buf, unsigned lba, unsigned nblk)
|
||||
{
|
||||
struct dos_partition *dp;
|
||||
struct disklabel *d;
|
||||
char *sec;
|
||||
int i;
|
||||
|
||||
if (!dsk_meta) {
|
||||
sec = dmadat->secbuf;
|
||||
dsk_start = 0;
|
||||
if (drvread(sec, DOSBBSECTOR, 1))
|
||||
return -1;
|
||||
dp = (void *)(sec + DOSPARTOFF);
|
||||
if (bootslice != 0) {
|
||||
i = bootslice - 1;
|
||||
if (dp[i].dp_typ != DOSPTYP_386BSD)
|
||||
return -1;
|
||||
} else {
|
||||
for (i = 0; i < NDOSPART; i++) {
|
||||
if ((dp[i].dp_typ == DOSPTYP_386BSD) &&
|
||||
(dp[i].dp_flag == 0x80))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != NDOSPART) {
|
||||
bootslice = i + 1;
|
||||
DPRINTF("Found an active fbsd slice. (%d)\n", i + 1);
|
||||
/*
|
||||
* Although dp_start is aligned within the disk
|
||||
* partition structure, DOSPARTOFF is 446, which
|
||||
* is only word (2) aligned, not longword (4)
|
||||
* aligned. Cope by using memcpy to fetch the
|
||||
* start of this partition.
|
||||
*/
|
||||
memcpy(&dsk_start, &dp[i].dp_start, 4);
|
||||
dsk_start = swap32(dsk_start);
|
||||
DPRINTF("dsk_start %x\n", dsk_start);
|
||||
if ((bootslice == 4) && (dsk_start == 0)) {
|
||||
disk_layout = DL_RAW;
|
||||
bootslice = 0;
|
||||
}
|
||||
}
|
||||
if (drvread(sec, dsk_start + LABELSECTOR, 1))
|
||||
return -1;
|
||||
d = (void *)(sec + LABELOFFSET);
|
||||
if ((d->d_magic == DISKMAGIC && d->d_magic2 == DISKMAGIC) ||
|
||||
(swap32(d->d_magic) == DISKMAGIC &&
|
||||
swap32(d->d_magic2) == DISKMAGIC)) {
|
||||
DPRINTF("p_size = %x\n",
|
||||
!d->d_partitions[bootpart].p_size);
|
||||
if (!d->d_partitions[bootpart].p_size) {
|
||||
printf("Invalid partition\n");
|
||||
return -1;
|
||||
}
|
||||
DPRINTF("p_offset %x, RAW %x\n",
|
||||
swap32(d->d_partitions[bootpart].p_offset),
|
||||
swap32(d->d_partitions[RAW_PART].p_offset));
|
||||
dsk_start += swap32(d->d_partitions[bootpart].p_offset);
|
||||
dsk_start -= swap32(d->d_partitions[RAW_PART].p_offset);
|
||||
if ((disk_layout == DL_UNKNOWN) && (bootslice == 0))
|
||||
disk_layout = DL_RAW;
|
||||
else if (disk_layout == DL_UNKNOWN)
|
||||
disk_layout = DL_SLICEPART;
|
||||
} else {
|
||||
disk_layout = DL_SLICE;
|
||||
DPRINTF("Invalid %s\n", "label");
|
||||
}
|
||||
DPRINTF("bootslice %d, bootpart %d, dsk_start %u\n", bootslice,
|
||||
bootpart, dsk_start);
|
||||
dsk_meta++;
|
||||
}
|
||||
return drvread(buf, dsk_start + lba, nblk);
|
||||
}
|
||||
|
||||
static int
|
||||
drvread(void *buf, unsigned lba, unsigned nblk)
|
||||
{
|
||||
static unsigned c = 0x2d5c7c2f;
|
||||
|
||||
printf("%c\b", c = c << 8 | c >> 24);
|
||||
return (avila_read((char *)buf, lba, nblk));
|
||||
}
|
||||
|
||||
#ifdef FIXUP_BOOT_DRV
|
||||
/*
|
||||
* fixup_boot_drv() will try to find the ROOTDEVNAME spec in the kernel
|
||||
* and change it to what was specified on the comandline or /boot.conf
|
||||
* file or to what was encountered on the disk. It will try to handle 3
|
||||
* different disk layouts, raw (dangerously dedicated), slice only and
|
||||
* slice + partition. It will look for the following strings in the
|
||||
* kernel, but if it is one of the first three, the string in the kernel
|
||||
* must use the correct form to match the actual disk layout:
|
||||
* - ufs:ad0a
|
||||
* - ufs:ad0s1
|
||||
* - ufs:ad0s1a
|
||||
* - ufs:ROOTDEVNAME
|
||||
* In the case of the first three strings, only the "a" at the end and
|
||||
* the "1" after the "s" will be modified, if they exist. The string
|
||||
* length will not be changed. In the case of the last string, the
|
||||
* whole string will be built up and nul, '\0' terminated.
|
||||
*/
|
||||
static void
|
||||
fixup_boot_drv(caddr_t addr, int klen, int bs, int bp)
|
||||
{
|
||||
const u_int8_t op[] = "ufs:ROOTDEVNAME";
|
||||
const u_int8_t op2[] = "ufs:ad0";
|
||||
u_int8_t *p, *ps;
|
||||
|
||||
DPRINTF("fixup_boot_drv: 0x%x, %d, slice %d, partition %d\n",
|
||||
(int)addr, klen, bs, bp);
|
||||
if (bs > 4)
|
||||
return;
|
||||
if (bp > 7)
|
||||
return;
|
||||
ps = memmem(addr, klen, op, sizeof(op));
|
||||
if (ps != NULL) {
|
||||
p = ps + 4; /* past ufs: */
|
||||
DPRINTF("Found it at 0x%x\n", (int)ps);
|
||||
p[0] = 'a'; p[1] = 'd'; p[2] = '0'; /* ad0 */
|
||||
p += 3;
|
||||
if (bs > 0) {
|
||||
/* append slice */
|
||||
*p++ = 's';
|
||||
*p++ = bs + '0';
|
||||
}
|
||||
if (disk_layout != DL_SLICE) {
|
||||
/* append partition */
|
||||
*p++ = bp + 'a';
|
||||
}
|
||||
*p = '\0';
|
||||
} else {
|
||||
ps = memmem(addr, klen, op2, sizeof(op2) - 1);
|
||||
if (ps != NULL) {
|
||||
p = ps + sizeof(op2) - 1;
|
||||
DPRINTF("Found it at 0x%x\n", (int)ps);
|
||||
if (*p == 's') {
|
||||
/* fix slice */
|
||||
p++;
|
||||
*p++ = bs + '0';
|
||||
}
|
||||
if (*p == 'a')
|
||||
*p = bp + 'a';
|
||||
}
|
||||
}
|
||||
if (ps == NULL) {
|
||||
printf("Could not locate \"%s\" to fix kernel boot device, "
|
||||
"check ROOTDEVNAME is set\n", op);
|
||||
return;
|
||||
}
|
||||
DPRINTF("Changed boot device to %s\n", ps);
|
||||
}
|
||||
#endif
|
@ -1,62 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 John Hay. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef ARM_BOOT_CF_ATA_H
|
||||
#define ARM_BOOT_CF_ATA_H
|
||||
|
||||
#define CF_DATA 0x00
|
||||
#define CF_ERROR 0x01
|
||||
#define CF_FEATURE 0x01
|
||||
#define CF_SECT_CNT 0x02
|
||||
#define CF_SECT_NUM 0x03
|
||||
#define CF_CYL_L 0x04
|
||||
#define CF_CYL_H 0x05
|
||||
#define CF_DRV_HEAD 0x06
|
||||
#define CF_D_MASTER 0x00
|
||||
#define CF_D_LBA 0x40
|
||||
#define CF_D_IBM 0xa0
|
||||
#define CF_STATUS 0x07
|
||||
#define CF_S_ERROR 0x01
|
||||
#define CF_S_INDEX 0x02
|
||||
#define CF_S_CORR 0x04
|
||||
#define CF_S_DRQ 0x08
|
||||
#define CF_S_DSC 0x10
|
||||
#define CF_S_DWF 0x20
|
||||
#define CF_S_READY 0x40
|
||||
#define CF_S_BUSY 0x80
|
||||
#define CF_COMMAND 0x07
|
||||
|
||||
/* This is according to the appnote, but Sam use 0x1e in avila_ata.c */
|
||||
#define CF_ALT_STATUS 0x16
|
||||
#define CF_ALT_DEV_CTR 0x16
|
||||
#define CF_ALT_DEV_CTR2 0x1e
|
||||
#define CF_A_IDS 0x02
|
||||
#define CF_A_RESET 0x04
|
||||
#define CF_A_4BIT 0x08
|
||||
|
||||
#define AVILA_IDE_GPIN 12
|
||||
|
||||
#endif /* !ARM_BOOT_CF_ATA_H */
|
@ -1,771 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 John Hay. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/ata.h>
|
||||
#include <sys/linker_set.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "cf_ata.h"
|
||||
|
||||
#include <machine/armreg.h>
|
||||
#include <arm/xscale/ixp425/ixp425reg.h>
|
||||
#include <dev/ic/ns16550.h>
|
||||
|
||||
struct board_config {
|
||||
const char *desc;
|
||||
int (*probe)(int boardtype_hint);
|
||||
void (*init)(void);
|
||||
};
|
||||
/* set of registered boards */
|
||||
SET_DECLARE(boards, struct board_config);
|
||||
#define BOARD_CONFIG(name, _desc) \
|
||||
static struct board_config name##config = { \
|
||||
.desc = _desc, \
|
||||
.probe = name##_probe, \
|
||||
.init = name##_init, \
|
||||
}; \
|
||||
DATA_SET(boards, name##config)
|
||||
|
||||
static u_int cputype;
|
||||
#define cpu_is_ixp43x() (cputype == CPU_ID_IXP435)
|
||||
static u_int8_t *ubase;
|
||||
|
||||
static u_int8_t uart_getreg(u_int8_t *, int);
|
||||
static void uart_setreg(u_int8_t *, int, u_int8_t);
|
||||
|
||||
static void cf_init(void);
|
||||
static void cf_clr(void);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
const char *
|
||||
board_init(void)
|
||||
{
|
||||
struct board_config **pbp;
|
||||
|
||||
cputype = cpu_id() & CPU_ID_CPU_MASK;
|
||||
|
||||
SET_FOREACH(pbp, boards)
|
||||
/* XXX pass down redboot board type */
|
||||
if ((*pbp)->probe(0)) {
|
||||
(*pbp)->init();
|
||||
return (*pbp)->desc;
|
||||
}
|
||||
/* XXX panic, unknown board type */
|
||||
return "???";
|
||||
}
|
||||
|
||||
/*
|
||||
* This should be called just before starting the kernel. This is so
|
||||
* that one can undo incompatible hardware settings.
|
||||
*/
|
||||
void
|
||||
clr_board(void)
|
||||
{
|
||||
cf_clr();
|
||||
}
|
||||
|
||||
/*
|
||||
* General support functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DELAY should delay for the number of microseconds.
|
||||
* The idea is that the inner loop should take 1us, so val is the
|
||||
* number of usecs to delay.
|
||||
*/
|
||||
void
|
||||
DELAY(int val)
|
||||
{
|
||||
volatile int sub;
|
||||
volatile int subsub;
|
||||
|
||||
sub = val;
|
||||
while(sub) {
|
||||
subsub = 3;
|
||||
while(subsub)
|
||||
subsub--;
|
||||
sub--;
|
||||
}
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
swap32(u_int32_t a)
|
||||
{
|
||||
return (((a & 0xff) << 24) | ((a & 0xff00) << 8) |
|
||||
((a & 0xff0000) >> 8) | ((a & 0xff000000) >> 24));
|
||||
}
|
||||
|
||||
u_int16_t
|
||||
swap16(u_int16_t val)
|
||||
{
|
||||
return (val << 8) | (val >> 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* uart related funcs
|
||||
*/
|
||||
static u_int8_t
|
||||
uart_getreg(u_int8_t *bas, int off)
|
||||
{
|
||||
return *((volatile u_int32_t *)(bas + (off << 2))) & 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
uart_setreg(u_int8_t *bas, int off, u_int8_t val)
|
||||
{
|
||||
*((volatile u_int32_t *)(bas + (off << 2))) = (u_int32_t)val;
|
||||
}
|
||||
|
||||
int
|
||||
getc(int seconds)
|
||||
{
|
||||
int c, delay, limit;
|
||||
|
||||
c = 0;
|
||||
delay = 10000;
|
||||
limit = seconds * 1000000/10000;
|
||||
while ((uart_getreg(ubase, REG_LSR) & LSR_RXRDY) == 0 && --limit)
|
||||
DELAY(delay);
|
||||
|
||||
if ((uart_getreg(ubase, REG_LSR) & LSR_RXRDY) == LSR_RXRDY)
|
||||
c = uart_getreg(ubase, REG_DATA);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
putchar(int ch)
|
||||
{
|
||||
int delay, limit;
|
||||
|
||||
delay = 500;
|
||||
limit = 20;
|
||||
while ((uart_getreg(ubase, REG_LSR) & LSR_THRE) == 0 && --limit)
|
||||
DELAY(delay);
|
||||
uart_setreg(ubase, REG_DATA, ch);
|
||||
|
||||
limit = 40;
|
||||
while ((uart_getreg(ubase, REG_LSR) & LSR_TEMT) == 0 && --limit)
|
||||
DELAY(delay);
|
||||
}
|
||||
|
||||
void
|
||||
xputchar(int ch)
|
||||
{
|
||||
if (ch == '\n')
|
||||
putchar('\r');
|
||||
putchar(ch);
|
||||
}
|
||||
|
||||
void
|
||||
putstr(const char *str)
|
||||
{
|
||||
while(*str)
|
||||
xputchar(*str++);
|
||||
}
|
||||
|
||||
void
|
||||
puthex8(u_int8_t ch)
|
||||
{
|
||||
const char *hex = "0123456789abcdef";
|
||||
|
||||
putchar(hex[ch >> 4]);
|
||||
putchar(hex[ch & 0xf]);
|
||||
}
|
||||
|
||||
void
|
||||
puthexlist(const u_int8_t *str, int length)
|
||||
{
|
||||
while(length) {
|
||||
puthex8(*str);
|
||||
putchar(' ');
|
||||
str++;
|
||||
length--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* CF/IDE functions.
|
||||
*
|
||||
*/
|
||||
|
||||
struct {
|
||||
u_int64_t dsize;
|
||||
u_int64_t total_secs;
|
||||
u_int8_t heads;
|
||||
u_int8_t sectors;
|
||||
u_int32_t cylinders;
|
||||
|
||||
u_int32_t *cs1to;
|
||||
u_int32_t *cs2to;
|
||||
|
||||
u_int8_t *cs1;
|
||||
u_int8_t *cs2;
|
||||
|
||||
u_int32_t use_lba;
|
||||
u_int32_t use_stream8;
|
||||
u_int32_t debug;
|
||||
|
||||
u_int8_t status;
|
||||
u_int8_t error;
|
||||
} dskinf;
|
||||
|
||||
static void cfenable16(void);
|
||||
static void cfdisable16(void);
|
||||
static u_int8_t cfread8(u_int32_t off);
|
||||
static u_int16_t cfread16(u_int32_t off);
|
||||
static void cfreadstream8(void *buf, int length);
|
||||
static void cfreadstream16(void *buf, int length);
|
||||
static void cfwrite8(u_int32_t off, u_int8_t val);
|
||||
static u_int8_t cfaltread8(u_int32_t off);
|
||||
static void cfaltwrite8(u_int32_t off, u_int8_t val);
|
||||
static int cfwait(u_int8_t mask);
|
||||
static int cfaltwait(u_int8_t mask);
|
||||
static int cfcmd(u_int32_t cmd, u_int32_t cylinder, u_int32_t head,
|
||||
u_int32_t sector, u_int32_t count, u_int32_t feature);
|
||||
static void cfreset(void);
|
||||
#ifdef DEBUG
|
||||
static int cfgetparams(void);
|
||||
#endif
|
||||
static void cfprintregs(void);
|
||||
|
||||
static void
|
||||
cf_init(void)
|
||||
{
|
||||
u_int8_t status;
|
||||
#ifdef DEBUG
|
||||
int rval;
|
||||
#endif
|
||||
|
||||
/* NB: board init routines setup other parts of dskinf */
|
||||
dskinf.use_stream8 = 0;
|
||||
dskinf.use_lba = 0;
|
||||
dskinf.debug = 1;
|
||||
|
||||
DPRINTF("cs1 %x, cs2 %x\n", dskinf.cs1, dskinf.cs2);
|
||||
|
||||
/* Setup the CF window */
|
||||
*dskinf.cs1to |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
|
||||
DPRINTF("t1 %x, ", *dskinf.cs1to);
|
||||
|
||||
*dskinf.cs2to |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
|
||||
DPRINTF("t2 %x\n", *dskinf.cs2to);
|
||||
|
||||
/* Detect if there is a disk. */
|
||||
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
|
||||
DELAY(1000);
|
||||
status = cfread8(CF_STATUS);
|
||||
if (status != 0x50)
|
||||
printf("cf-ata0 %x\n", (u_int32_t)status);
|
||||
if (status == 0xff) {
|
||||
printf("cf_ata0: No disk!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cfreset();
|
||||
|
||||
if (dskinf.use_stream8) {
|
||||
DPRINTF("setting %d bit mode.\n", 8);
|
||||
cfwrite8(CF_FEATURE, 0x01); /* Enable 8 bit transfers */
|
||||
cfwrite8(CF_COMMAND, ATA_SETFEATURES);
|
||||
cfaltwait(CF_S_READY);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
rval = cfgetparams();
|
||||
if (rval)
|
||||
return;
|
||||
#endif
|
||||
dskinf.use_lba = 1;
|
||||
dskinf.debug = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cf_clr(void)
|
||||
{
|
||||
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
|
||||
cfaltwait(CF_S_READY);
|
||||
cfwrite8(CF_FEATURE, 0x81); /* Enable 8 bit transfers */
|
||||
cfwrite8(CF_COMMAND, ATA_SETFEATURES);
|
||||
cfaltwait(CF_S_READY);
|
||||
}
|
||||
|
||||
static void
|
||||
cfenable16(void)
|
||||
{
|
||||
u_int32_t val;
|
||||
|
||||
val = *dskinf.cs1to;
|
||||
*dskinf.cs1to = val &~ EXP_BYTE_EN;
|
||||
DELAY(100);
|
||||
#if 0
|
||||
DPRINTF("%s: cs1 timing reg %x\n", *dskinf.cs1to, __func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
cfdisable16(void)
|
||||
{
|
||||
u_int32_t val;
|
||||
|
||||
DELAY(100);
|
||||
val = *dskinf.cs1to;
|
||||
*dskinf.cs1to = val | EXP_BYTE_EN;
|
||||
#if 0
|
||||
DPRINTF("%s: cs1 timing reg %x\n", *dskinf.cs1to, __func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
static u_int8_t
|
||||
cfread8(u_int32_t off)
|
||||
{
|
||||
volatile u_int8_t *vp;
|
||||
|
||||
vp = (volatile u_int8_t *)(dskinf.cs1 + off);
|
||||
return *vp;
|
||||
}
|
||||
|
||||
static void
|
||||
cfreadstream8(void *buf, int length)
|
||||
{
|
||||
u_int8_t *lbuf;
|
||||
u_int8_t tmp;
|
||||
|
||||
lbuf = buf;
|
||||
while (length) {
|
||||
tmp = cfread8(CF_DATA);
|
||||
*lbuf = tmp;
|
||||
#ifdef DEBUG
|
||||
if (dskinf.debug && (length > (512 - 32))) {
|
||||
if ((length % 16) == 0)
|
||||
xputchar('\n');
|
||||
puthex8(tmp);
|
||||
putchar(' ');
|
||||
}
|
||||
#endif
|
||||
lbuf++;
|
||||
length--;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (dskinf.debug)
|
||||
xputchar('\n');
|
||||
#endif
|
||||
}
|
||||
|
||||
static u_int16_t
|
||||
cfread16(u_int32_t off)
|
||||
{
|
||||
volatile u_int16_t *vp;
|
||||
|
||||
vp = (volatile u_int16_t *)(dskinf.cs1 + off);
|
||||
return swap16(*vp);
|
||||
}
|
||||
|
||||
static void
|
||||
cfreadstream16(void *buf, int length)
|
||||
{
|
||||
u_int16_t *lbuf;
|
||||
|
||||
length = length / 2;
|
||||
cfenable16();
|
||||
lbuf = buf;
|
||||
while (length--) {
|
||||
*lbuf = cfread16(CF_DATA);
|
||||
lbuf++;
|
||||
}
|
||||
cfdisable16();
|
||||
}
|
||||
|
||||
static void
|
||||
cfwrite8(u_int32_t off, u_int8_t val)
|
||||
{
|
||||
volatile u_int8_t *vp;
|
||||
|
||||
vp = (volatile u_int8_t *)(dskinf.cs1 + off);
|
||||
*vp = val;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
cfwrite16(u_int32_t off, u_int16_t val)
|
||||
{
|
||||
volatile u_int16_t *vp;
|
||||
|
||||
vp = (volatile u_int16_t *)(dskinf.cs1 + off);
|
||||
*vp = val;
|
||||
}
|
||||
#endif
|
||||
|
||||
static u_int8_t
|
||||
cfaltread8(u_int32_t off)
|
||||
{
|
||||
volatile u_int8_t *vp;
|
||||
|
||||
off &= 0x0f;
|
||||
vp = (volatile u_int8_t *)(dskinf.cs2 + off);
|
||||
return *vp;
|
||||
}
|
||||
|
||||
static void
|
||||
cfaltwrite8(u_int32_t off, u_int8_t val)
|
||||
{
|
||||
volatile u_int8_t *vp;
|
||||
|
||||
/*
|
||||
* This is documented in the Intel appnote 302456.
|
||||
*/
|
||||
off &= 0x0f;
|
||||
vp = (volatile u_int8_t *)(dskinf.cs2 + off);
|
||||
*vp = val;
|
||||
}
|
||||
|
||||
static int
|
||||
cfwait(u_int8_t mask)
|
||||
{
|
||||
u_int8_t status;
|
||||
u_int32_t tout;
|
||||
|
||||
tout = 0;
|
||||
while (tout <= 5000000) {
|
||||
status = cfread8(CF_STATUS);
|
||||
if (status == 0xff) {
|
||||
printf("%s: master: no status, reselecting\n",
|
||||
__func__);
|
||||
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
|
||||
DELAY(1);
|
||||
status = cfread8(CF_STATUS);
|
||||
}
|
||||
if (status == 0xff)
|
||||
return -1;
|
||||
dskinf.status = status;
|
||||
if (!(status & CF_S_BUSY)) {
|
||||
if (status & CF_S_ERROR) {
|
||||
dskinf.error = cfread8(CF_ERROR);
|
||||
printf("%s: error, status 0x%x error 0x%x\n",
|
||||
__func__, status, dskinf.error);
|
||||
}
|
||||
if ((status & mask) == mask) {
|
||||
DPRINTF("%s: status 0x%x mask 0x%x tout %u\n",
|
||||
__func__, status, mask, tout);
|
||||
return (status & CF_S_ERROR);
|
||||
}
|
||||
}
|
||||
if (tout > 1000) {
|
||||
tout += 1000;
|
||||
DELAY(1000);
|
||||
} else {
|
||||
tout += 10;
|
||||
DELAY(10);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
cfaltwait(u_int8_t mask)
|
||||
{
|
||||
u_int8_t status;
|
||||
u_int32_t tout;
|
||||
|
||||
tout = 0;
|
||||
while (tout <= 5000000) {
|
||||
status = cfaltread8(CF_ALT_STATUS);
|
||||
if (status == 0xff) {
|
||||
printf("cfaltwait: master: no status, reselecting\n");
|
||||
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
|
||||
DELAY(1);
|
||||
status = cfread8(CF_STATUS);
|
||||
}
|
||||
if (status == 0xff)
|
||||
return -1;
|
||||
dskinf.status = status;
|
||||
if (!(status & CF_S_BUSY)) {
|
||||
if (status & CF_S_ERROR)
|
||||
dskinf.error = cfread8(CF_ERROR);
|
||||
if ((status & mask) == mask) {
|
||||
DPRINTF("cfaltwait: tout %u\n", tout);
|
||||
return (status & CF_S_ERROR);
|
||||
}
|
||||
}
|
||||
if (tout > 1000) {
|
||||
tout += 1000;
|
||||
DELAY(1000);
|
||||
} else {
|
||||
tout += 10;
|
||||
DELAY(10);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
cfcmd(u_int32_t cmd, u_int32_t cylinder, u_int32_t head, u_int32_t sector,
|
||||
u_int32_t count, u_int32_t feature)
|
||||
{
|
||||
if (cfwait(0) < 0) {
|
||||
printf("cfcmd: timeout\n");
|
||||
return -1;
|
||||
}
|
||||
cfwrite8(CF_FEATURE, feature);
|
||||
cfwrite8(CF_CYL_L, cylinder);
|
||||
cfwrite8(CF_CYL_H, cylinder >> 8);
|
||||
if (dskinf.use_lba)
|
||||
cfwrite8(CF_DRV_HEAD, CF_D_IBM | CF_D_LBA | head);
|
||||
else
|
||||
cfwrite8(CF_DRV_HEAD, CF_D_IBM | head);
|
||||
cfwrite8(CF_SECT_NUM, sector);
|
||||
cfwrite8(CF_SECT_CNT, count);
|
||||
cfwrite8(CF_COMMAND, cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cfreset(void)
|
||||
{
|
||||
u_int8_t status;
|
||||
u_int32_t tout;
|
||||
|
||||
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
|
||||
DELAY(1);
|
||||
#ifdef DEBUG
|
||||
cfprintregs();
|
||||
#endif
|
||||
cfread8(CF_STATUS);
|
||||
cfaltwrite8(CF_ALT_DEV_CTR, CF_A_IDS | CF_A_RESET);
|
||||
DELAY(10000);
|
||||
cfaltwrite8(CF_ALT_DEV_CTR, CF_A_IDS);
|
||||
DELAY(10000);
|
||||
cfread8(CF_ERROR);
|
||||
DELAY(3000);
|
||||
|
||||
for (tout = 0; tout < 310000; tout++) {
|
||||
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
|
||||
DELAY(1);
|
||||
status = cfread8(CF_STATUS);
|
||||
if (!(status & CF_S_BUSY))
|
||||
break;
|
||||
DELAY(100);
|
||||
}
|
||||
DELAY(1);
|
||||
if (status & CF_S_BUSY) {
|
||||
cfprintregs();
|
||||
printf("cfreset: Status stayed busy after reset.\n");
|
||||
}
|
||||
DPRINTF("cfreset: finished, tout %u\n", tout);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static int
|
||||
cfgetparams(void)
|
||||
{
|
||||
u_int8_t *buf;
|
||||
|
||||
buf = (u_int8_t *)(0x170000);
|
||||
p_memset((char *)buf, 0, 1024);
|
||||
/* Select the drive. */
|
||||
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
|
||||
DELAY(1);
|
||||
cfcmd(ATA_ATA_IDENTIFY, 0, 0, 0, 0, 0);
|
||||
if (cfaltwait(CF_S_READY | CF_S_DSC | CF_S_DRQ)) {
|
||||
printf("cfgetparams: ATA_IDENTIFY failed.\n");
|
||||
return -1;
|
||||
}
|
||||
if (dskinf.use_stream8)
|
||||
cfreadstream8(buf, 512);
|
||||
else
|
||||
cfreadstream16(buf, 512);
|
||||
if (dskinf.debug)
|
||||
cfprintregs();
|
||||
#if 0
|
||||
memcpy(&dskinf.ata_params, buf, sizeof(struct ata_params));
|
||||
dskinf.cylinders = dskinf.ata_params.cylinders;
|
||||
dskinf.heads = dskinf.ata_params.heads;
|
||||
dskinf.sectors = dskinf.ata_params.sectors;
|
||||
printf("dsk0: sec %x, hd %x, cyl %x, stat %x, err %x\n",
|
||||
(u_int32_t)dskinf.ata_params.sectors,
|
||||
(u_int32_t)dskinf.ata_params.heads,
|
||||
(u_int32_t)dskinf.ata_params.cylinders,
|
||||
(u_int32_t)dskinf.status,
|
||||
(u_int32_t)dskinf.error);
|
||||
#endif
|
||||
dskinf.status = cfread8(CF_STATUS);
|
||||
if (dskinf.debug)
|
||||
printf("cfgetparams: ata_params * %x, stat %x\n",
|
||||
(u_int32_t)buf, (u_int32_t)dskinf.status);
|
||||
return 0;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
static void
|
||||
cfprintregs(void)
|
||||
{
|
||||
u_int8_t rv;
|
||||
|
||||
putstr("cfprintregs: regs error ");
|
||||
rv = cfread8(CF_ERROR);
|
||||
puthex8(rv);
|
||||
putstr(", count ");
|
||||
rv = cfread8(CF_SECT_CNT);
|
||||
puthex8(rv);
|
||||
putstr(", sect ");
|
||||
rv = cfread8(CF_SECT_NUM);
|
||||
puthex8(rv);
|
||||
putstr(", cyl low ");
|
||||
rv = cfread8(CF_CYL_L);
|
||||
puthex8(rv);
|
||||
putstr(", cyl high ");
|
||||
rv = cfread8(CF_CYL_H);
|
||||
puthex8(rv);
|
||||
putstr(", drv head ");
|
||||
rv = cfread8(CF_DRV_HEAD);
|
||||
puthex8(rv);
|
||||
putstr(", status ");
|
||||
rv = cfread8(CF_STATUS);
|
||||
puthex8(rv);
|
||||
putstr("\n");
|
||||
}
|
||||
|
||||
int
|
||||
avila_read(char *dest, unsigned source, unsigned length)
|
||||
{
|
||||
if (dskinf.use_lba == 0 && source == 0)
|
||||
source++;
|
||||
if (dskinf.debug)
|
||||
printf("avila_read: 0x%x, sect %d num secs %d\n",
|
||||
(u_int32_t)dest, source, length);
|
||||
while (length) {
|
||||
cfwait(CF_S_READY);
|
||||
/* cmd, cyl, head, sect, count, feature */
|
||||
cfcmd(ATA_READ, (source >> 8) & 0xffff, source >> 24,
|
||||
source & 0xff, 1, 0);
|
||||
|
||||
cfwait(CF_S_READY | CF_S_DRQ | CF_S_DSC);
|
||||
if (dskinf.use_stream8)
|
||||
cfreadstream8(dest, 512);
|
||||
else
|
||||
cfreadstream16(dest, 512);
|
||||
length--;
|
||||
source++;
|
||||
dest += 512;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gateworks Avila Support.
|
||||
*/
|
||||
static int
|
||||
avila_probe(int boardtype_hint)
|
||||
{
|
||||
volatile u_int32_t *cs;
|
||||
/*
|
||||
* Redboot only configure the chip selects that are needed, so
|
||||
* use that to figure out if it is an Avila or ADI board. The
|
||||
* Avila boards use CS2 and ADI does not.
|
||||
*/
|
||||
cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
|
||||
return (*cs != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
avila_init(void)
|
||||
{
|
||||
/* Config the serial port. RedBoot should do the rest. */
|
||||
ubase = (u_int8_t *)(IXP425_UART0_HWBASE);
|
||||
|
||||
dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS1_OFFSET);
|
||||
dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
|
||||
dskinf.cs1 = (u_int8_t *)IXP425_EXP_BUS_CS1_HWBASE;
|
||||
dskinf.cs2 = (u_int8_t *)IXP425_EXP_BUS_CS2_HWBASE;
|
||||
|
||||
cf_init();
|
||||
}
|
||||
BOARD_CONFIG(avila, "Gateworks Avila");
|
||||
|
||||
/*
|
||||
* Gateworks Cambria Support.
|
||||
*/
|
||||
static int
|
||||
cambria_probe(int boardtype_hint)
|
||||
{
|
||||
return cpu_is_ixp43x();
|
||||
}
|
||||
|
||||
static void
|
||||
cambria_init(void)
|
||||
{
|
||||
/* Config the serial port. RedBoot should do the rest. */
|
||||
ubase = (u_int8_t *)(IXP425_UART0_HWBASE);
|
||||
|
||||
dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET);
|
||||
dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS4_OFFSET);
|
||||
dskinf.cs1 = (u_int8_t *)CAMBRIA_CFSEL0_HWBASE;
|
||||
dskinf.cs2 = (u_int8_t *)CAMBRIA_CFSEL1_HWBASE;
|
||||
|
||||
cf_init();
|
||||
}
|
||||
BOARD_CONFIG(cambria, "Gateworks Cambria");
|
||||
|
||||
/*
|
||||
* Pronghorn Metro Support.
|
||||
*/
|
||||
static int
|
||||
pronghorn_probe(int boardtype_hint)
|
||||
{
|
||||
volatile u_int32_t *cs;
|
||||
/*
|
||||
* Redboot only configure the chip selects that are needed, so
|
||||
* use that to figure out if it is an Avila or ADI board. The
|
||||
* Avila boards use CS2 and ADI does not.
|
||||
*/
|
||||
cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
|
||||
return (*cs == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
pronghorn_init(void)
|
||||
{
|
||||
/* Config the serial port. RedBoot should do the rest. */
|
||||
ubase = (u_int8_t *)(IXP425_UART1_HWBASE);
|
||||
|
||||
dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET);
|
||||
dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS4_OFFSET);
|
||||
dskinf.cs1 = (u_int8_t *)IXP425_EXP_BUS_CS3_HWBASE;
|
||||
dskinf.cs2 = (u_int8_t *)IXP425_EXP_BUS_CS4_HWBASE;
|
||||
|
||||
cf_init();
|
||||
}
|
||||
BOARD_CONFIG(pronghorn, "Pronghorn Metro");
|
@ -1,67 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 John Hay. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef ARM_BOOT_LIB_H
|
||||
#define ARM_BOOT_LIB_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
int main(void);
|
||||
|
||||
void DELAY(int);
|
||||
|
||||
int getc(int);
|
||||
void putchar(int);
|
||||
void xputchar(int);
|
||||
void putstr(const char *);
|
||||
void puthex8(u_int8_t);
|
||||
void puthexlist(const u_int8_t *, int);
|
||||
void printf(const char *fmt,...);
|
||||
|
||||
void bzero(void *, size_t);
|
||||
char *strcpy(char *to, const char *from);
|
||||
int strcmp(const char *to, const char *from);
|
||||
int p_strlen(const char *);
|
||||
int p_memcmp(const char *, const char *, unsigned);
|
||||
void *memchr(const void *, int, size_t);
|
||||
void memcpy(void *to, const void *from, unsigned size);
|
||||
void *memmem(const void *, size_t, const void *, size_t);
|
||||
void p_memset(char *buffer, char value, int size);
|
||||
|
||||
#define strlen p_strlen
|
||||
#define memcmp p_memcmp
|
||||
#define memset p_memset
|
||||
|
||||
u_int16_t swap16(u_int16_t);
|
||||
u_int32_t swap32(u_int32_t);
|
||||
|
||||
const char *board_init(void);
|
||||
void clr_board(void);
|
||||
int avila_read(char*, unsigned, unsigned);
|
||||
u_int cpu_id(void);
|
||||
|
||||
#endif /* !ARM_BOOT_LIB_H */
|
@ -1,11 +1,20 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
LOADER_UFS_SUPPORT?= yes
|
||||
LOADER_CD9660_SUPPORT?= no
|
||||
LOADER_MSDOS_SUPPORT?= no
|
||||
LOADER_EXT2FS_SUPPORT?= no
|
||||
LOADER_NET_SUPPORT?= yes
|
||||
LOADER_NFS_SUPPORT?= yes
|
||||
LOADER_TFTP_SUPPORT?= no
|
||||
LOADER_GZIP_SUPPORT?= no
|
||||
LOADER_BZIP2_SUPPORT?= no
|
||||
|
||||
FILES= ubldr ubldr.bin
|
||||
.include <bsd.init.mk>
|
||||
|
||||
FILES+= ubldr ubldr.bin
|
||||
|
||||
NEWVERSWHAT= "U-Boot loader" ${MACHINE_ARCH}
|
||||
BINDIR?= /boot
|
||||
INSTALLFLAGS= -b
|
||||
WARNS?= 1
|
||||
# Address at which ubldr will be loaded.
|
||||
@ -19,83 +28,10 @@ SRCS= start.S conf.c self_reloc.c vers.c
|
||||
CWARNFLAGS.self_reloc.c+= -Wno-error=maybe-uninitialized
|
||||
.endif
|
||||
|
||||
.if !defined(LOADER_NO_DISK_SUPPORT)
|
||||
LOADER_DISK_SUPPORT?= yes
|
||||
.else
|
||||
LOADER_DISK_SUPPORT= no
|
||||
.endif
|
||||
LOADER_UFS_SUPPORT?= yes
|
||||
LOADER_CD9660_SUPPORT?= no
|
||||
LOADER_EXT2FS_SUPPORT?= no
|
||||
.if ${MK_NAND} != "no"
|
||||
LOADER_NANDFS_SUPPORT?= yes
|
||||
.else
|
||||
LOADER_NANDFS_SUPPORT?= no
|
||||
.endif
|
||||
LOADER_NET_SUPPORT?= yes
|
||||
LOADER_NFS_SUPPORT?= yes
|
||||
LOADER_TFTP_SUPPORT?= no
|
||||
LOADER_GZIP_SUPPORT?= no
|
||||
LOADER_BZIP2_SUPPORT?= no
|
||||
.if ${MK_FDT} != "no"
|
||||
LOADER_FDT_SUPPORT= yes
|
||||
.else
|
||||
LOADER_FDT_SUPPORT= no
|
||||
.endif
|
||||
|
||||
.if ${LOADER_DISK_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_DISK_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_UFS_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_UFS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_CD9660_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_CD9660_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_EXT2FS_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_EXT2FS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_NANDFS_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_NANDFS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_GZIP_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_GZIP_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_BZIP2_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_BZIP2_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_NET_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_NET_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_NFS_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_NFS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_TFTP_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_TFTP_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_FDT_SUPPORT} == "yes"
|
||||
CFLAGS+= -I${.CURDIR}/../../fdt
|
||||
CFLAGS+= -I${.OBJDIR}/../../fdt
|
||||
CFLAGS+= -DLOADER_FDT_SUPPORT
|
||||
LIBUBOOT_FDT= ${.OBJDIR}/../../uboot/fdt/libuboot_fdt.a
|
||||
LIBFDT= ${.OBJDIR}/../../fdt/libfdt.a
|
||||
.endif
|
||||
|
||||
.if ${MK_FORTH} != "no"
|
||||
# Enable BootForth
|
||||
BOOT_FORTH= yes
|
||||
CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl
|
||||
CFLAGS+= -I${.CURDIR}/../../ficl/arm
|
||||
LIBFICL= ${.OBJDIR}/../../ficl/libficl.a
|
||||
.endif
|
||||
HELP_FILES+= help.uboot ${BOOTSRC}/fdt/help.fdt
|
||||
|
||||
# Always add MI sources
|
||||
.PATH: ${.CURDIR}/../../common
|
||||
.include "${.CURDIR}/../../common/Makefile.inc"
|
||||
CFLAGS+= -I${.CURDIR}/../../common
|
||||
CFLAGS+= -I.
|
||||
|
||||
CLEANFILES+= loader.help
|
||||
.include "${BOOTSRC}/loader.mk"
|
||||
|
||||
CFLAGS+= -ffreestanding -msoft-float
|
||||
|
||||
@ -103,29 +39,15 @@ LDFLAGS= -nostdlib -static -T ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
|
||||
LDFLAGS+= -Wl,-znotext
|
||||
|
||||
# Pull in common loader code
|
||||
.PATH: ${.CURDIR}/../../uboot/common
|
||||
.include "${.CURDIR}/../../uboot/common/Makefile.inc"
|
||||
CFLAGS+= -I${.CURDIR}/../../uboot/common
|
||||
|
||||
# U-Boot standalone support library
|
||||
LIBUBOOT= ${.OBJDIR}/../../uboot/lib/libuboot.a
|
||||
CFLAGS+= -I${.CURDIR}/../../uboot/lib
|
||||
CFLAGS+= -I${.OBJDIR}/../../uboot/lib
|
||||
.include "${BOOTSRC}/uboot.mk"
|
||||
|
||||
CFLAGS+= -fPIC
|
||||
|
||||
# clang doesn't understand %D as a specifier to printf
|
||||
NO_WERROR.clang=
|
||||
|
||||
DPADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBUBOOT_FDT} ${LIBSA}
|
||||
LDADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBUBOOT_FDT} ${LIBSA}
|
||||
|
||||
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
|
||||
|
||||
loader.help: help.common help.uboot ${.CURDIR}/../../fdt/help.fdt
|
||||
cat ${.ALLSRC} | \
|
||||
awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET}
|
||||
|
||||
ldscript.abs:
|
||||
echo "UBLDR_LOADADDR = ${UBLDR_LOADADDR};" >${.TARGET}
|
||||
|
||||
@ -145,15 +67,4 @@ ubldr.bin: ubldr.pie
|
||||
|
||||
CLEANFILES+= ldscript.abs ldscript.pie ubldr ubldr.pie ubldr.bin
|
||||
|
||||
.if !defined(LOADER_ONLY)
|
||||
.PATH: ${.CURDIR}/../../forth
|
||||
.include "${.CURDIR}/../../forth/Makefile.inc"
|
||||
|
||||
# Install loader.rc.
|
||||
FILES+= loader.rc
|
||||
# Put sample menu.rc on disk but don't enable it by default.
|
||||
FILES+= menu.rc
|
||||
FILESNAME_menu.rc= menu.rc.sample
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -88,6 +88,12 @@ ptblread(void *d, void *buf, size_t blocks, uint64_t offset)
|
||||
dev = (struct disk_devdesc *)d;
|
||||
od = (struct open_disk *)dev->d_opendata;
|
||||
|
||||
/*
|
||||
* The strategy function assumes the offset is in units of 512 byte
|
||||
* sectors. For larger sector sizes, we need to adjust the offset to
|
||||
* match the actual sector size.
|
||||
*/
|
||||
offset *= (od->sectorsize / 512);
|
||||
/*
|
||||
* As the GPT backup partition is located at the end of the disk,
|
||||
* to avoid reading past disk end, flag bcache not to use RA.
|
||||
|
@ -73,7 +73,8 @@ struct devsw md_dev = {
|
||||
md_open,
|
||||
md_close,
|
||||
noioctl,
|
||||
md_print
|
||||
md_print,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
|
171
sys/boot/defs.mk
Normal file
171
sys/boot/defs.mk
Normal file
@ -0,0 +1,171 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
||||
.if !defined(__BOOT_DEFS_MK__)
|
||||
__BOOT_DEFS_MK__=${MFILE}
|
||||
|
||||
BOOTSRC= ${SRCTOP}/sys/boot
|
||||
EFISRC= ${BOOTSRC}/efi
|
||||
EFIINC= ${EFISRC}/include
|
||||
EFIINCMD= ${EFIINC}/${MACHINE}
|
||||
FDTSRC= ${BOOTSRC}/fdt
|
||||
FICLSRC= ${BOOTSRC}/ficl
|
||||
LDRSRC= ${BOOTSRC}/common
|
||||
SASRC= ${BOOTSRC}/libsa
|
||||
SYSDIR= ${SRCTOP}/sys
|
||||
UBOOTSRC= ${BOOTSRC}/uboot
|
||||
ZFSSRC= ${BOOTSRC}/zfs
|
||||
|
||||
BOOTOBJ= ${OBJTOP}/sys/boot
|
||||
|
||||
# BINDIR is where we install
|
||||
BINDIR?= /boot
|
||||
|
||||
# NB: The makefiles depend on these being empty when we don't build forth.
|
||||
.if ${MK_FORTH} != "no"
|
||||
LIBFICL= ${BOOTOBJ}/ficl/libficl.a
|
||||
.if ${MACHINE} == "i386"
|
||||
LIBFICL32= ${LIBFICL}
|
||||
.else
|
||||
LIBFICL32= ${BOOTOBJ}/ficl32/libficl.a
|
||||
.endif
|
||||
.endif
|
||||
LIBSA= ${BOOTOBJ}/libsa/libsa.a
|
||||
.if ${MACHINE} == "i386"
|
||||
LIBSA32= ${LIBSA}
|
||||
.else
|
||||
LIBSA32= ${BOOTOBJ}/libsa32/libsa32.a
|
||||
.endif
|
||||
|
||||
# Standard options:
|
||||
|
||||
# Filesystem support
|
||||
.if ${LOADER_CD9660_SUPPORT:Uno} == "yes"
|
||||
CFLAGS+= -DLOADER_CD9660_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_EXT2FS_SUPPORT:Uno} == "yes"
|
||||
CFLAGS+= -DLOADER_EXT2FS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_MSDOS_SUPPORT:Uno} == "yes"
|
||||
CFLAGS+= -DLOADER_MSDOS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_NANDFS_SUPPORT:U${MK_NAND}} == "yes"
|
||||
CFLAGS+= -DLOADER_NANDFS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_UFS_SUPPORT:Uyes} == "yes"
|
||||
CFLAGS+= -DLOADER_UFS_SUPPORT
|
||||
.endif
|
||||
|
||||
# Compression
|
||||
.if ${LOADER_GZIP_SUPPORT:Uno} == "yes"
|
||||
CFLAGS+= -DLOADER_GZIP_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_BZIP2_SUPPORT:Uno} == "yes"
|
||||
CFLAGS+= -DLOADER_BZIP2_SUPPORT
|
||||
.endif
|
||||
|
||||
# Network related things
|
||||
.if ${LOADER_NET_SUPPORT:Uno} == "yes"
|
||||
CFLAGS+= -DLOADER_NET_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_NFS_SUPPORT:Uno} == "yes"
|
||||
CFLAGS+= -DLOADER_NFS_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_TFTP_SUPPORT:Uno} == "yes"
|
||||
CFLAGS+= -DLOADER_TFTP_SUPPORT
|
||||
.endif
|
||||
|
||||
# Disk and partition support
|
||||
.if ${LOADER_DISK_SUPPORT:Uyes} == "yes"
|
||||
CFLAGS+= -DLOADER_DISK_SUPPORT
|
||||
.if ${LOADER_GPT_SUPPORT:Uyes} == "yes"
|
||||
CFLAGS+= -DLOADER_GPT_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_MBR_SUPPORT:Uyes} == "yes"
|
||||
CFLAGS+= -DLOADER_MBR_SUPPORT
|
||||
.endif
|
||||
|
||||
# GELI Support, with backward compat hooks
|
||||
.if defined(HAVE_GELI)
|
||||
.if defined(LOADER_NO_GELI_SUPPORT)
|
||||
MK_LOADER_GELI=no
|
||||
.warning "Please move from LOADER_NO_GELI_SUPPORT to WITHOUT_LOADER_GELI"
|
||||
.endif
|
||||
.if defined(LOADER_GELI_SUPPORT)
|
||||
MK_LOADER_GELI=yes
|
||||
.warning "Please move from LOADER_GELI_SUPPORT to WITH_LOADER_GELI"
|
||||
.endif
|
||||
.if ${MK_LOADER_GELI} == "yes"
|
||||
CFLAGS+= -DLOADER_GELI_SUPPORT
|
||||
CFLAGS+= -I${BOOTSRC}/geli
|
||||
LIBGELIBOOT= ${BOOTOBJ}/geli/libgeliboot.a
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
|
||||
CFLAGS+= -I${SYSDIR}
|
||||
|
||||
# All PowerPC builds are 32 bit. We have no 64-bit loaders on powerpc
|
||||
# or powerpc64.
|
||||
.if ${MACHINE_ARCH} == "powerpc64"
|
||||
CFLAGS+= -m32 -mcpu=powerpc
|
||||
.endif
|
||||
|
||||
# For amd64, there's a bit of mixed bag. Some of the tree (i386, lib*32) is
|
||||
# build 32-bit and some 64-bit (lib*, efi). Centralize all the 32-bit magic here
|
||||
# and activate it when DO32 is explicitly defined to be 1.
|
||||
.if ${MACHINE_ARCH} == "amd64" && ${DO32:U0} == 1
|
||||
CFLAGS+= -m32 -mcpu=i386
|
||||
# LD_FLAGS is passed directly to ${LD}, not via ${CC}:
|
||||
LD_FLAGS+= -m elf_i386_fbsd
|
||||
AFLAGS+= --32
|
||||
.endif
|
||||
|
||||
# Make sure we use the machine link we're about to create
|
||||
CFLAGS+=-I.
|
||||
|
||||
_ILINKS=machine
|
||||
.if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64"
|
||||
_ILINKS+=${MACHINE_CPUARCH}
|
||||
.endif
|
||||
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
|
||||
_ILINKS+=x86
|
||||
.endif
|
||||
CLEANFILES+=${_ILINKS}
|
||||
|
||||
all: ${PROG}
|
||||
|
||||
beforedepend: ${_ILINKS}
|
||||
beforebuild: ${_ILINKS}
|
||||
|
||||
# Ensure that the links exist without depending on it when it exists which
|
||||
# causes all the modules to be rebuilt when the directory pointed to changes.
|
||||
.for _link in ${_ILINKS}
|
||||
.if !exists(${.OBJDIR}/${_link})
|
||||
${OBJS}: ${_link}
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
.NOPATH: ${_ILINKS}
|
||||
|
||||
${_ILINKS}:
|
||||
@case ${.TARGET} in \
|
||||
machine) \
|
||||
if [ ${DO32:U0} -eq 0 ]; then \
|
||||
path=${SYSDIR}/${MACHINE}/include ; \
|
||||
else \
|
||||
path=${SYSDIR}/${MACHINE:C/amd64/i386/}/include ; \
|
||||
fi ;; \
|
||||
*) \
|
||||
path=${SYSDIR}/${.TARGET:T}/include ;; \
|
||||
esac ; \
|
||||
path=`(cd $$path && /bin/pwd)` ; \
|
||||
${ECHO} ${.TARGET:T} "->" $$path ; \
|
||||
ln -fhs $$path ${.TARGET:T}
|
||||
|
||||
# For loader implementations, we generate a loader.help file. This can be suppressed by
|
||||
# setting HELP_FILES to nothing.
|
||||
HELP_FILES= ${LDRSRC}/help.common
|
||||
|
||||
.endif # __BOOT_DEFS_MK__
|
@ -1,6 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
.include <bsd.init.mk>
|
||||
|
||||
# In-tree GCC does not support __attribute__((ms_abi)), but gcc newer
|
||||
# than 4.5 supports it.
|
||||
|
@ -1,7 +1,5 @@
|
||||
# $FreeBSD$
|
||||
|
||||
BINDIR?= /boot
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "i386"
|
||||
CFLAGS+= -march=i386
|
||||
CFLAGS+= -mno-aes
|
||||
|
@ -2,16 +2,14 @@
|
||||
|
||||
MAN=
|
||||
|
||||
.include "../Makefile.inc"
|
||||
.include <bsd.init.mk>
|
||||
|
||||
MK_SSP= no
|
||||
MK_FORTH= no
|
||||
|
||||
PROG= boot1.sym
|
||||
INTERNALPROG=
|
||||
WARNS?= 3
|
||||
|
||||
# Include bcache code.
|
||||
HAVE_BCACHE= yes
|
||||
WARNS?= 6
|
||||
|
||||
# We implement a slightly non-standard %S in that it always takes a
|
||||
# CHAR16 that's common in UEFI-land instead of a wchar_t. This only
|
||||
@ -21,71 +19,46 @@ HAVE_BCACHE= yes
|
||||
CWARNFLAGS.boot1.c+= -Wno-format
|
||||
|
||||
# Disable warnings that are currently incompatible with the zfs boot code
|
||||
CWARNFLAGS.zfs.c += -Wno-incompatible-pointer-types-discards-qualifiers
|
||||
CWARNFLAGS.zfs.c += -Wno-missing-variable-declarations
|
||||
CWARNFLAGS.zfs.c += -Wno-array-bounds
|
||||
CWARNFLAGS.zfs.c += -Wno-cast-align
|
||||
CWARNFLAGS.zfs.c += -Wno-cast-qual
|
||||
CWARNFLAGS.zfs.c += -Wno-missing-prototypes
|
||||
CWARNFLAGS.zfs.c += -Wno-sign-compare
|
||||
CWARNFLAGS.zfs.c += -Wno-unused-parameter
|
||||
CWARNFLAGS.zfs.c += -Wno-unused-function
|
||||
CWARNFLAGS.skein.c += -Wno-cast-align
|
||||
.if ${COMPILER_TYPE} == "clang"
|
||||
CWARNFLAGS.skein.c += -Wno-missing-variable-declarations
|
||||
.else if ${COMPILER_TYPE} == "gcc"
|
||||
CWARNFLAGS.skein.c += -Wno-missing-declarations
|
||||
.endif
|
||||
CWARNFLAGS.zfs_module.c += -Wno-array-bounds
|
||||
CWARNFLAGS.zfs_module.c += -Wno-cast-align
|
||||
CWARNFLAGS.zfs_module.c += -Wno-cast-qual
|
||||
CWARNFLAGS.zfs_module.c += -Wno-missing-prototypes
|
||||
CWARNFLAGS.zfs_module.c += -Wno-sign-compare
|
||||
CWARNFLAGS.zfs_module.c += -Wno-unused-parameter
|
||||
CWARNFLAGS.zfs_module.c += -Wno-unused-function
|
||||
|
||||
# architecture-specific loader code
|
||||
SRCS= boot1.c self_reloc.c start.S
|
||||
SRCS= boot1.c self_reloc.c start.S ufs_module.c
|
||||
.if ${MK_ZFS} != "no"
|
||||
.PATH: ${.CURDIR}/../../../crypto/skein
|
||||
SRCS+= skein.c skein_block.c
|
||||
# Do not unroll skein loops, reduce code size
|
||||
CFLAGS+= -DSKEIN_LOOP=111
|
||||
.PATH: ${.CURDIR}/../../zfs
|
||||
SRCS+= zfs.c
|
||||
SRCS+= zfs_module.c
|
||||
CFLAGS+= -I${ZFSSRC}
|
||||
CFLAGS+= -I${SYSDIR}/cddl/boot/zfs
|
||||
CFLAGS+= -DEFI_ZFS_BOOT
|
||||
LIBZFSBOOT= ${BOOTOBJ}/zfs/libzfsboot.a
|
||||
.endif
|
||||
|
||||
.if ${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} > 40201
|
||||
CWARNFLAGS.self_reloc.c+= -Wno-error=maybe-uninitialized
|
||||
.endif
|
||||
|
||||
# Always add MI sources
|
||||
.PATH: ${.CURDIR}/../../common
|
||||
.include "${.CURDIR}/../../common/Makefile.inc"
|
||||
CFLAGS+= -I${.CURDIR}/../../common
|
||||
|
||||
.PATH: ${.CURDIR}/arch/${MACHINE}
|
||||
|
||||
CFLAGS+= -I.
|
||||
CFLAGS+= -I${.CURDIR}/../include
|
||||
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
|
||||
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
|
||||
CFLAGS+= -I${.CURDIR}/../../..
|
||||
CFLAGS+= -I${EFIINC}
|
||||
CFLAGS+= -I${EFIINCMD}
|
||||
CFLAGS+= -I${SYSDIR}/contrib/dev/acpica/include
|
||||
CFLAGS+= -DEFI_UFS_BOOT
|
||||
.ifdef(EFI_DEBUG)
|
||||
CFLAGS+= -DEFI_DEBUG
|
||||
.endif
|
||||
|
||||
.if ${MK_ZFS} != "no"
|
||||
CFLAGS+= -I${.CURDIR}/../../zfs/
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs/
|
||||
CFLAGS+= -I${.CURDIR}/../../../crypto/skein
|
||||
CFLAGS+= -DEFI_ZFS_BOOT
|
||||
.endif
|
||||
|
||||
# Always add MI sources and REGULAR efi loader bits
|
||||
.PATH: ${.CURDIR}/../loader/arch/${MACHINE}
|
||||
.PATH: ${.CURDIR}/../loader
|
||||
.PATH: ${.CURDIR}/../../common
|
||||
CFLAGS+= -I${.CURDIR}/../../common
|
||||
.PATH: ${EFISRC}/loader/arch/${MACHINE}
|
||||
.PATH: ${EFISRC}/loader
|
||||
.PATH: ${LDRSRC}
|
||||
CFLAGS+= -I${LDRSRC}
|
||||
|
||||
FILES= boot1.efi boot1.efifat
|
||||
FILESMODE_boot1.efi= ${BINMODE}
|
||||
|
||||
LDSCRIPT= ${.CURDIR}/../loader/arch/${MACHINE}/ldscript.${MACHINE}
|
||||
LDSCRIPT= ${EFISRC}/loader/arch/${MACHINE}/ldscript.${MACHINE}
|
||||
LDFLAGS+= -Wl,-T${LDSCRIPT},-Bsymbolic,-znotext -shared
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "aarch64"
|
||||
@ -96,15 +69,15 @@ CFLAGS+= -fPIC
|
||||
LDFLAGS+= -Wl,-znocombreloc
|
||||
.endif
|
||||
|
||||
LIBEFI= ${.OBJDIR}/../libefi/libefi.a
|
||||
LIBEFI= ${BOOTOBJ}/efi/libefi/libefi.a
|
||||
|
||||
#
|
||||
# Add libstand for the runtime functions used by the compiler - for example
|
||||
# __aeabi_* (arm) or __divdi3 (i386).
|
||||
# as well as required string and memory functions for all platforms.
|
||||
#
|
||||
DPADD+= ${LIBEFI} ${LIBSA}
|
||||
LDADD+= ${LIBEFI} ${LIBSA}
|
||||
DPADD+= ${LIBEFI} ${LIBZFSBOOT} ${LIBSA}
|
||||
LDADD+= ${LIBEFI} ${LIBZFSBOOT} ${LIBSA}
|
||||
|
||||
DPADD+= ${LDSCRIPT}
|
||||
|
||||
@ -130,7 +103,7 @@ boot1.efi: ${PROG}
|
||||
SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} \
|
||||
${OBJCOPY} -j .peheader -j .text -j .sdata -j .data \
|
||||
-j .dynamic -j .dynsym -j .rel.dyn \
|
||||
-j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
|
||||
-j .rela.dyn -j .reloc -j .eh_frame \
|
||||
--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
|
||||
|
||||
boot1.o: ${SASRC}/ufsread.c
|
||||
@ -151,21 +124,6 @@ boot1.efifat: boot1.efi
|
||||
xz -d -c ${.CURDIR}/fat-${MACHINE}.tmpl.xz > ${.TARGET}
|
||||
${DD} if=${.ALLSRC} of=${.TARGET} seek=${BOOT1_OFFSET} conv=notrunc
|
||||
|
||||
CLEANFILES= boot1.efi boot1.efifat
|
||||
CLEANFILES+= boot1.efi boot1.efifat
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
beforedepend ${OBJS}: machine
|
||||
|
||||
CLEANFILES+= machine
|
||||
|
||||
machine: .NOMETA
|
||||
ln -sf ${.CURDIR}/../../../${MACHINE}/include machine
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
|
||||
beforedepend ${OBJS}: x86
|
||||
CLEANFILES+= x86
|
||||
|
||||
x86: .NOMETA
|
||||
ln -sf ${.CURDIR}/../../../x86/include x86
|
||||
.endif
|
||||
|
@ -23,179 +23,61 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/disk.h>
|
||||
#include <machine/elf.h>
|
||||
#include <machine/stdarg.h>
|
||||
#include <stand.h>
|
||||
#include <disk.h>
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
#include <efiprot.h>
|
||||
#include <eficonsctl.h>
|
||||
#ifdef EFI_ZFS_BOOT
|
||||
#include <libzfs.h>
|
||||
#endif
|
||||
typedef CHAR16 efi_char;
|
||||
#include <efichar.h>
|
||||
|
||||
#include <bootstrap.h>
|
||||
|
||||
#include "efi_drivers.h"
|
||||
#include "efizfs.h"
|
||||
#include "boot_module.h"
|
||||
#include "paths.h"
|
||||
|
||||
static void efi_panic(EFI_STATUS s, const char *fmt, ...) __dead2 __printflike(2, 3);
|
||||
#ifdef EFI_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf(fmt, ##args)
|
||||
#define DSTALL(d) BS->Stall(d)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...) {}
|
||||
#define DSTALL(d) {}
|
||||
#endif
|
||||
|
||||
struct arch_switch archsw; /* MI/MD interface boundary */
|
||||
|
||||
static const efi_driver_t *efi_drivers[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
extern struct console efi_console;
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
extern struct console comconsole;
|
||||
extern struct console nullconsole;
|
||||
#endif
|
||||
|
||||
static const boot_module_t *boot_modules[] =
|
||||
{
|
||||
#ifdef EFI_ZFS_BOOT
|
||||
uint64_t pool_guid;
|
||||
&zfs_module,
|
||||
#endif
|
||||
|
||||
struct fs_ops *file_system[] = {
|
||||
#ifdef EFI_ZFS_BOOT
|
||||
&zfs_fsops,
|
||||
#endif
|
||||
&dosfs_fsops,
|
||||
#ifdef EFI_UFS_BOOT
|
||||
&ufs_fsops,
|
||||
&ufs_module
|
||||
#endif
|
||||
&cd9660_fsops,
|
||||
&nfs_fsops,
|
||||
&gzipfs_fsops,
|
||||
&bzipfs_fsops,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct devsw *devsw[] = {
|
||||
&efipart_hddev,
|
||||
&efipart_fddev,
|
||||
&efipart_cddev,
|
||||
#ifdef EFI_ZFS_BOOT
|
||||
&zfs_dev,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
struct console *consoles[] = {
|
||||
&efi_console,
|
||||
NULL
|
||||
};
|
||||
|
||||
static EFI_LOADED_IMAGE *boot_image;
|
||||
static EFI_DEVICE_PATH *imgpath;
|
||||
static EFI_DEVICE_PATH *imgprefix;
|
||||
|
||||
/* Definitions we don't actually need for boot, but we need to define
|
||||
* to make the linker happy.
|
||||
*/
|
||||
struct file_format *file_formats[] = { NULL };
|
||||
|
||||
struct netif_driver *netif_drivers[] = { NULL };
|
||||
|
||||
static int
|
||||
efi_autoload(void)
|
||||
{
|
||||
printf("******** Boot block should not call autoload\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
efi_copyin(const void *src __unused, vm_offset_t dest __unused,
|
||||
const size_t len __unused)
|
||||
{
|
||||
printf("******** Boot block should not call copyin\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
efi_copyout(vm_offset_t src __unused, void *dest __unused,
|
||||
const size_t len __unused)
|
||||
{
|
||||
printf("******** Boot block should not call copyout\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
efi_readin(int fd __unused, vm_offset_t dest __unused,
|
||||
const size_t len __unused)
|
||||
{
|
||||
printf("******** Boot block should not call readin\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#define NUM_BOOT_MODULES nitems(boot_modules)
|
||||
/* The initial number of handles used to query EFI for partitions. */
|
||||
#define NUM_HANDLES_INIT 24
|
||||
|
||||
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
|
||||
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
|
||||
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
|
||||
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
|
||||
static EFI_GUID FreeBSDBootVarGUID = FREEBSD_BOOT_VAR_GUID;
|
||||
|
||||
static EFI_STATUS
|
||||
do_load(const char *filepath, void **bufp, size_t *bufsize)
|
||||
/*
|
||||
* Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
|
||||
* memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
|
||||
* EFI methods.
|
||||
*/
|
||||
void *
|
||||
Malloc(size_t len, const char *file __unused, int line __unused)
|
||||
{
|
||||
struct stat st;
|
||||
void *buf = NULL;
|
||||
int fd, err;
|
||||
size_t fsize, remaining;
|
||||
ssize_t readsize;
|
||||
void *out;
|
||||
|
||||
if ((fd = open(filepath, O_RDONLY)) < 0) {
|
||||
return (ENOTSUP);
|
||||
}
|
||||
if (BS->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
|
||||
return (out);
|
||||
|
||||
if ((err = fstat(fd, &st)) != 0) {
|
||||
goto close_file;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
fsize = st.st_size;
|
||||
|
||||
if ((buf = malloc(fsize)) == NULL) {
|
||||
err = ENOMEM;
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
remaining = fsize;
|
||||
|
||||
do {
|
||||
if ((readsize = read(fd, buf, fsize)) < 0) {
|
||||
err = (-readsize);
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
remaining -= readsize;
|
||||
} while(remaining != 0);
|
||||
|
||||
close(fd);
|
||||
*bufsize = st.st_size;
|
||||
*bufp = buf;
|
||||
|
||||
close_file:
|
||||
close(fd);
|
||||
|
||||
return errno_to_efi_status(err);
|
||||
|
||||
free_buf:
|
||||
free(buf);
|
||||
goto close_file;
|
||||
void
|
||||
Free(void *buf, const char *file __unused, int line __unused)
|
||||
{
|
||||
if (buf != NULL)
|
||||
(void)BS->FreePool(buf);
|
||||
}
|
||||
|
||||
static EFI_STATUS
|
||||
@ -215,274 +97,97 @@ efi_setenv_freebsd_wcs(const char *varname, CHAR16 *valstr)
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static int
|
||||
probe_fs(const char *filepath)
|
||||
/*
|
||||
* nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
|
||||
* FALSE otherwise.
|
||||
*/
|
||||
static BOOLEAN
|
||||
nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
|
||||
{
|
||||
int fd;
|
||||
size_t len;
|
||||
|
||||
if ((fd = open(filepath, O_RDONLY)) < 0) {
|
||||
return (ENOTSUP);
|
||||
}
|
||||
if (imgpath == NULL || imgpath->Type != devpath->Type ||
|
||||
imgpath->SubType != devpath->SubType)
|
||||
return (FALSE);
|
||||
|
||||
close(fd);
|
||||
len = DevicePathNodeLength(imgpath);
|
||||
if (len != DevicePathNodeLength(devpath))
|
||||
return (FALSE);
|
||||
|
||||
return (0);
|
||||
return (memcmp(imgpath, devpath, (size_t)len) == 0);
|
||||
}
|
||||
|
||||
static int
|
||||
probe_dev(struct devsw *dev, int unit, const char *filepath)
|
||||
/*
|
||||
* device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
|
||||
* in imgpath and devpath match up to their respective occurrences of a
|
||||
* media node, FALSE otherwise.
|
||||
*/
|
||||
static BOOLEAN
|
||||
device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
|
||||
{
|
||||
struct devdesc currdev;
|
||||
char *devname;
|
||||
int err;
|
||||
|
||||
currdev.d_dev = dev;
|
||||
currdev.d_type = currdev.d_dev->dv_type;
|
||||
currdev.d_unit = unit;
|
||||
currdev.d_opendata = NULL;
|
||||
devname = efi_fmtdev(&currdev);
|
||||
if (imgpath == NULL)
|
||||
return (FALSE);
|
||||
|
||||
env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
|
||||
env_nounset);
|
||||
while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) {
|
||||
if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) &&
|
||||
IsDevicePathType(devpath, MEDIA_DEVICE_PATH))
|
||||
return (TRUE);
|
||||
|
||||
err = probe_fs(filepath);
|
||||
if (!nodes_match(imgpath, devpath))
|
||||
return (FALSE);
|
||||
|
||||
return (err);
|
||||
imgpath = NextDevicePathNode(imgpath);
|
||||
devpath = NextDevicePathNode(devpath);
|
||||
}
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static bool
|
||||
check_preferred(EFI_HANDLE *h)
|
||||
/*
|
||||
* devpath_last returns the last non-path end node in devpath.
|
||||
*/
|
||||
static EFI_DEVICE_PATH *
|
||||
devpath_last(EFI_DEVICE_PATH *devpath)
|
||||
{
|
||||
EFI_DEVICE_PATH *path = efi_lookup_devpath(h);
|
||||
bool out;
|
||||
|
||||
if ((path = efi_lookup_devpath(h)) == NULL)
|
||||
return (false);
|
||||
while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
|
||||
devpath = NextDevicePathNode(devpath);
|
||||
|
||||
out = efi_devpath_is_prefix(imgpath, path) ||
|
||||
efi_devpath_is_prefix(imgprefix, path);
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
bool
|
||||
efi_zfs_is_preferred(EFI_HANDLE *h)
|
||||
{
|
||||
return (check_preferred(h));
|
||||
}
|
||||
|
||||
static int
|
||||
load_preferred(EFI_LOADED_IMAGE *img, const char *filepath, void **bufp,
|
||||
size_t *bufsize, EFI_HANDLE *handlep)
|
||||
{
|
||||
pdinfo_list_t *pdi_list;
|
||||
pdinfo_t *dp, *pp;
|
||||
char *devname;
|
||||
|
||||
#ifdef EFI_ZFS_BOOT
|
||||
/* Did efi_zfs_probe() detect the boot pool? */
|
||||
if (pool_guid != 0) {
|
||||
struct zfs_devdesc currdev;
|
||||
|
||||
currdev.d_dev = &zfs_dev;
|
||||
currdev.d_unit = 0;
|
||||
currdev.d_type = currdev.d_dev->dv_type;
|
||||
currdev.d_opendata = NULL;
|
||||
currdev.pool_guid = pool_guid;
|
||||
currdev.root_guid = 0;
|
||||
devname = efi_fmtdev(&currdev);
|
||||
|
||||
env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
|
||||
env_nounset);
|
||||
|
||||
if (probe_fs(filepath) == 0 &&
|
||||
do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
|
||||
*handlep = efizfs_get_handle_by_guid(pool_guid);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
#endif /* EFI_ZFS_BOOT */
|
||||
|
||||
/* We have device lists for hd, cd, fd, walk them all. */
|
||||
pdi_list = efiblk_get_pdinfo_list(&efipart_hddev);
|
||||
STAILQ_FOREACH(dp, pdi_list, pd_link) {
|
||||
struct disk_devdesc currdev;
|
||||
|
||||
currdev.d_dev = &efipart_hddev;
|
||||
currdev.d_type = currdev.d_dev->dv_type;
|
||||
currdev.d_unit = dp->pd_unit;
|
||||
currdev.d_opendata = NULL;
|
||||
currdev.d_slice = -1;
|
||||
currdev.d_partition = -1;
|
||||
devname = efi_fmtdev(&currdev);
|
||||
|
||||
env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
|
||||
env_nounset);
|
||||
|
||||
if (check_preferred(dp->pd_handle) &&
|
||||
probe_fs(filepath) == 0 &&
|
||||
do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
|
||||
*handlep = dp->pd_handle;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Assuming GPT partitioning. */
|
||||
STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
|
||||
if (check_preferred(pp->pd_handle)) {
|
||||
currdev.d_slice = pp->pd_unit;
|
||||
currdev.d_partition = 255;
|
||||
devname = efi_fmtdev(&currdev);
|
||||
|
||||
env_setenv("currdev", EV_VOLATILE, devname,
|
||||
efi_setcurrdev, env_nounset);
|
||||
|
||||
if (probe_fs(filepath) == 0 &&
|
||||
do_load(filepath, bufp, bufsize) ==
|
||||
EFI_SUCCESS) {
|
||||
*handlep = pp->pd_handle;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdi_list = efiblk_get_pdinfo_list(&efipart_cddev);
|
||||
STAILQ_FOREACH(dp, pdi_list, pd_link) {
|
||||
if ((dp->pd_handle == img->DeviceHandle ||
|
||||
dp->pd_alias == img->DeviceHandle ||
|
||||
check_preferred(dp->pd_handle)) &&
|
||||
probe_dev(&efipart_cddev, dp->pd_unit, filepath) == 0 &&
|
||||
do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
|
||||
*handlep = dp->pd_handle;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
pdi_list = efiblk_get_pdinfo_list(&efipart_fddev);
|
||||
STAILQ_FOREACH(dp, pdi_list, pd_link) {
|
||||
if ((dp->pd_handle == img->DeviceHandle ||
|
||||
check_preferred(dp->pd_handle)) &&
|
||||
probe_dev(&efipart_cddev, dp->pd_unit, filepath) == 0 &&
|
||||
do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
|
||||
*handlep = dp->pd_handle;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
static int
|
||||
load_all(const char *filepath, void **bufp, size_t *bufsize,
|
||||
EFI_HANDLE *handlep)
|
||||
{
|
||||
pdinfo_list_t *pdi_list;
|
||||
pdinfo_t *dp, *pp;
|
||||
zfsinfo_list_t *zfsi_list;
|
||||
zfsinfo_t *zi;
|
||||
char *devname;
|
||||
|
||||
#ifdef EFI_ZFS_BOOT
|
||||
zfsi_list = efizfs_get_zfsinfo_list();
|
||||
STAILQ_FOREACH(zi, zfsi_list, zi_link) {
|
||||
struct zfs_devdesc currdev;
|
||||
|
||||
currdev.d_dev = &zfs_dev;
|
||||
currdev.d_unit = 0;
|
||||
currdev.d_type = currdev.d_dev->dv_type;
|
||||
currdev.d_opendata = NULL;
|
||||
currdev.pool_guid = zi->zi_pool_guid;
|
||||
currdev.root_guid = 0;
|
||||
devname = efi_fmtdev(&currdev);
|
||||
|
||||
env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
|
||||
env_nounset);
|
||||
|
||||
if (probe_fs(filepath) == 0 &&
|
||||
do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
|
||||
*handlep = zi->zi_handle;
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
#endif /* EFI_ZFS_BOOT */
|
||||
|
||||
/* We have device lists for hd, cd, fd, walk them all. */
|
||||
pdi_list = efiblk_get_pdinfo_list(&efipart_hddev);
|
||||
STAILQ_FOREACH(dp, pdi_list, pd_link) {
|
||||
struct disk_devdesc currdev;
|
||||
|
||||
currdev.d_dev = &efipart_hddev;
|
||||
currdev.d_type = currdev.d_dev->dv_type;
|
||||
currdev.d_unit = dp->pd_unit;
|
||||
currdev.d_opendata = NULL;
|
||||
currdev.d_slice = -1;
|
||||
currdev.d_partition = -1;
|
||||
devname = efi_fmtdev(&currdev);
|
||||
|
||||
env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
|
||||
env_nounset);
|
||||
|
||||
if (probe_fs(filepath) == 0 &&
|
||||
do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
|
||||
*handlep = dp->pd_handle;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Assuming GPT partitioning. */
|
||||
STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
|
||||
currdev.d_slice = pp->pd_unit;
|
||||
currdev.d_partition = 255;
|
||||
devname = efi_fmtdev(&currdev);
|
||||
|
||||
env_setenv("currdev", EV_VOLATILE, devname,
|
||||
efi_setcurrdev, env_nounset);
|
||||
|
||||
if (probe_fs(filepath) == 0 &&
|
||||
do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
|
||||
*handlep = pp->pd_handle;
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdi_list = efiblk_get_pdinfo_list(&efipart_cddev);
|
||||
STAILQ_FOREACH(dp, pdi_list, pd_link) {
|
||||
if (probe_dev(&efipart_cddev, dp->pd_unit, filepath) == 0 &&
|
||||
do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
|
||||
*handlep = dp->pd_handle;
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
pdi_list = efiblk_get_pdinfo_list(&efipart_fddev);
|
||||
STAILQ_FOREACH(dp, pdi_list, pd_link) {
|
||||
if (probe_dev(&efipart_fddev, dp->pd_unit, filepath) == 0 &&
|
||||
do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
|
||||
*handlep = dp->pd_handle;
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
return (devpath);
|
||||
}
|
||||
|
||||
/*
|
||||
* load_loader attempts to load the loader image data.
|
||||
*
|
||||
* It tries each module and its respective devices, identified by mod->probe,
|
||||
* in order until a successful load occurs at which point it returns EFI_SUCCESS
|
||||
* and EFI_NOT_FOUND otherwise.
|
||||
*
|
||||
* Only devices which have preferred matching the preferred parameter are tried.
|
||||
*/
|
||||
static EFI_STATUS
|
||||
load_loader(EFI_HANDLE *handlep, void **bufp, size_t *bufsize)
|
||||
load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
|
||||
size_t *bufsize, BOOLEAN preferred)
|
||||
{
|
||||
/* Try the preferred handles first, then all the handles */
|
||||
if (load_preferred(boot_image, PATH_LOADER_EFI, bufp, bufsize,
|
||||
handlep) == 0) {
|
||||
return (0);
|
||||
}
|
||||
UINTN i;
|
||||
dev_info_t *dev;
|
||||
const boot_module_t *mod;
|
||||
|
||||
if (load_all(PATH_LOADER_EFI, bufp, bufsize, handlep) == 0) {
|
||||
return (0);
|
||||
}
|
||||
for (i = 0; i < NUM_BOOT_MODULES; i++) {
|
||||
mod = boot_modules[i];
|
||||
for (dev = mod->devices(); dev != NULL; dev = dev->next) {
|
||||
if (dev->preferred != preferred)
|
||||
continue;
|
||||
|
||||
if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
|
||||
EFI_SUCCESS) {
|
||||
*devinfop = dev;
|
||||
*modp = mod;
|
||||
return (EFI_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (EFI_NOT_FOUND);
|
||||
}
|
||||
@ -497,27 +202,20 @@ try_boot(void)
|
||||
size_t bufsize, loadersize, cmdsize;
|
||||
void *buf, *loaderbuf;
|
||||
char *cmd;
|
||||
EFI_HANDLE fshandle;
|
||||
dev_info_t *dev;
|
||||
const boot_module_t *mod;
|
||||
EFI_HANDLE loaderhandle;
|
||||
EFI_LOADED_IMAGE *loaded_image;
|
||||
EFI_STATUS status;
|
||||
EFI_DEVICE_PATH *fspath;
|
||||
|
||||
status = load_loader(&fshandle, &loaderbuf, &loadersize);
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
fspath = NULL;
|
||||
if (status == EFI_SUCCESS) {
|
||||
status = BS->OpenProtocol(fshandle, &DevicePathGUID,
|
||||
(void **)&fspath, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
|
||||
if (status != EFI_SUCCESS) {
|
||||
status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
|
||||
FALSE);
|
||||
if (status != EFI_SUCCESS) {
|
||||
DPRINTF("Failed to get image DevicePath (%lu)\n",
|
||||
EFI_ERROR_CODE(status));
|
||||
}
|
||||
DPRINTF("filesystem device path: %s\n", devpath_str(fspath));
|
||||
printf("Failed to load '%s'\n", PATH_LOADER_EFI);
|
||||
return (status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -532,9 +230,9 @@ try_boot(void)
|
||||
*/
|
||||
cmd = NULL;
|
||||
cmdsize = 0;
|
||||
status = do_load(PATH_DOTCONFIG, &buf, &bufsize);
|
||||
status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
|
||||
if (status == EFI_NOT_FOUND)
|
||||
status = do_load(PATH_CONFIG, &buf, &bufsize);
|
||||
status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
|
||||
if (status == EFI_SUCCESS) {
|
||||
cmdsize = bufsize + 1;
|
||||
cmd = malloc(cmdsize);
|
||||
@ -546,25 +244,24 @@ try_boot(void)
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if ((status = BS->LoadImage(TRUE, IH, efi_devpath_last_node(fspath),
|
||||
if ((status = BS->LoadImage(TRUE, IH, devpath_last(dev->devpath),
|
||||
loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
|
||||
printf("Failed to load image, size: %zu, (%lu)\n",
|
||||
loadersize, EFI_ERROR_CODE(status));
|
||||
printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
|
||||
mod->name, loadersize, EFI_ERROR_CODE(status));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if ((status = BS->OpenProtocol(loaderhandle, &LoadedImageGUID,
|
||||
(VOID**)&loaded_image, IH, NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL)) != EFI_SUCCESS) {
|
||||
printf("Failed to query LoadedImage (%lu)\n",
|
||||
EFI_ERROR_CODE(status));
|
||||
if ((status = BS->HandleProtocol(loaderhandle, &LoadedImageGUID,
|
||||
(VOID**)&loaded_image)) != EFI_SUCCESS) {
|
||||
printf("Failed to query LoadedImage provided by %s (%lu)\n",
|
||||
mod->name, EFI_ERROR_CODE(status));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (cmd != NULL)
|
||||
printf(" command args: %s\n", cmd);
|
||||
|
||||
loaded_image->DeviceHandle = fshandle;
|
||||
loaded_image->DeviceHandle = dev->devhandle;
|
||||
loaded_image->LoadOptionsSize = cmdsize;
|
||||
loaded_image->LoadOptions = cmd;
|
||||
|
||||
@ -582,8 +279,8 @@ try_boot(void)
|
||||
|
||||
if ((status = BS->StartImage(loaderhandle, NULL, NULL)) !=
|
||||
EFI_SUCCESS) {
|
||||
printf("Failed to start image (%lu)\n",
|
||||
EFI_ERROR_CODE(status));
|
||||
printf("Failed to start image provided by %s (%lu)\n",
|
||||
mod->name, EFI_ERROR_CODE(status));
|
||||
loaded_image->LoadOptionsSize = 0;
|
||||
loaded_image->LoadOptions = NULL;
|
||||
}
|
||||
@ -599,37 +296,142 @@ errout:
|
||||
return (status);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
main(int argc __unused, CHAR16 *argv[] __unused)
|
||||
/*
|
||||
* probe_handle determines if the passed handle represents a logical partition
|
||||
* if it does it uses each module in order to probe it and if successful it
|
||||
* returns EFI_SUCCESS.
|
||||
*/
|
||||
static EFI_STATUS
|
||||
probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
dev_info_t *devinfo;
|
||||
EFI_BLOCK_IO *blkio;
|
||||
EFI_DEVICE_PATH *devpath;
|
||||
EFI_STATUS status;
|
||||
UINTN i;
|
||||
|
||||
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
|
||||
UINTN i, max_dim, best_mode, cols, rows;
|
||||
CHAR16 *text;
|
||||
/* Figure out if we're dealing with an actual partition. */
|
||||
status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
|
||||
if (status == EFI_UNSUPPORTED)
|
||||
return (status);
|
||||
|
||||
archsw.arch_autoload = efi_autoload;
|
||||
archsw.arch_getdev = efi_getdev;
|
||||
archsw.arch_copyin = efi_copyin;
|
||||
archsw.arch_copyout = efi_copyout;
|
||||
archsw.arch_readin = efi_readin;
|
||||
#ifdef EFI_ZFS_BOOT
|
||||
/* Note this needs to be set before ZFS init. */
|
||||
archsw.arch_zfs_probe = efi_zfs_probe;
|
||||
if (status != EFI_SUCCESS) {
|
||||
DPRINTF("\nFailed to query DevicePath (%lu)\n",
|
||||
EFI_ERROR_CODE(status));
|
||||
return (status);
|
||||
}
|
||||
#ifdef EFI_DEBUG
|
||||
{
|
||||
CHAR16 *text = efi_devpath_name(devpath);
|
||||
DPRINTF("probing: %S\n", text);
|
||||
efi_free_devpath_name(text);
|
||||
}
|
||||
#endif
|
||||
status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
|
||||
if (status == EFI_UNSUPPORTED)
|
||||
return (status);
|
||||
|
||||
/* Init the time source */
|
||||
efi_time_init();
|
||||
cons_probe();
|
||||
if (status != EFI_SUCCESS) {
|
||||
DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
|
||||
EFI_ERROR_CODE(status));
|
||||
return (status);
|
||||
}
|
||||
|
||||
if (!blkio->Media->LogicalPartition)
|
||||
return (EFI_UNSUPPORTED);
|
||||
|
||||
*preferred = device_paths_match(imgpath, devpath);
|
||||
|
||||
/* Run through each module, see if it can load this partition */
|
||||
for (i = 0; i < NUM_BOOT_MODULES; i++) {
|
||||
devinfo = malloc(sizeof(*devinfo));
|
||||
if (devinfo == NULL) {
|
||||
DPRINTF("\nFailed to allocate devinfo\n");
|
||||
continue;
|
||||
}
|
||||
devinfo->dev = blkio;
|
||||
devinfo->devpath = devpath;
|
||||
devinfo->devhandle = h;
|
||||
devinfo->devdata = NULL;
|
||||
devinfo->preferred = *preferred;
|
||||
devinfo->next = NULL;
|
||||
|
||||
status = boot_modules[i]->probe(devinfo);
|
||||
if (status == EFI_SUCCESS)
|
||||
return (EFI_SUCCESS);
|
||||
free(devinfo);
|
||||
}
|
||||
|
||||
return (EFI_UNSUPPORTED);
|
||||
}
|
||||
|
||||
/*
|
||||
* probe_handle_status calls probe_handle and outputs the returned status
|
||||
* of the call.
|
||||
*/
|
||||
static void
|
||||
probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
BOOLEAN preferred;
|
||||
|
||||
preferred = FALSE;
|
||||
status = probe_handle(h, imgpath, &preferred);
|
||||
|
||||
DPRINTF("probe: ");
|
||||
switch (status) {
|
||||
case EFI_UNSUPPORTED:
|
||||
printf(".");
|
||||
DPRINTF(" not supported\n");
|
||||
break;
|
||||
case EFI_SUCCESS:
|
||||
if (preferred) {
|
||||
printf("%c", '*');
|
||||
DPRINTF(" supported (preferred)\n");
|
||||
} else {
|
||||
printf("%c", '+');
|
||||
DPRINTF(" supported\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("x");
|
||||
DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status));
|
||||
break;
|
||||
}
|
||||
DSTALL(500000);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
|
||||
{
|
||||
EFI_HANDLE *handles;
|
||||
EFI_LOADED_IMAGE *img;
|
||||
EFI_DEVICE_PATH *imgpath;
|
||||
EFI_STATUS status;
|
||||
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
|
||||
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
|
||||
UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
|
||||
CHAR16 *text;
|
||||
|
||||
/* Basic initialization*/
|
||||
ST = Xsystab;
|
||||
IH = Ximage;
|
||||
BS = ST->BootServices;
|
||||
RS = ST->RuntimeServices;
|
||||
|
||||
/* Set up the console, so printf works. */
|
||||
status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
|
||||
(VOID **)&ConsoleControl);
|
||||
if (status == EFI_SUCCESS)
|
||||
(void)ConsoleControl->SetMode(ConsoleControl,
|
||||
EfiConsoleControlScreenText);
|
||||
/*
|
||||
* Reset the console and find the best text mode.
|
||||
*/
|
||||
conout = ST->ConOut;
|
||||
conout->Reset(conout, TRUE);
|
||||
max_dim = best_mode = 0;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
for (i = 0; ; i++) {
|
||||
status = conout->QueryMode(conout, i, &cols, &rows);
|
||||
if (EFI_ERROR(status))
|
||||
break;
|
||||
@ -638,79 +440,89 @@ main(int argc __unused, CHAR16 *argv[] __unused)
|
||||
best_mode = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_dim > 0)
|
||||
if (max_dim > 0)
|
||||
conout->SetMode(conout, best_mode);
|
||||
|
||||
conout->EnableCursor(conout, TRUE);
|
||||
conout->ClearScreen(conout);
|
||||
|
||||
/* Print this here, so people know it's at least starting. */
|
||||
printf("\n>> FreeBSD EFI boot block\n");
|
||||
printf(" Loader path: %s\n\n", PATH_LOADER_EFI);
|
||||
|
||||
/* Get the image path and trim it to get the disk on which we
|
||||
* found this loader.
|
||||
*/
|
||||
if ((status = BS->OpenProtocol(IH, &LoadedImageGUID,
|
||||
(VOID**)&boot_image, IH, NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL)) != EFI_SUCCESS) {
|
||||
panic("Failed to query LoadedImage (%lu)\n",
|
||||
EFI_ERROR_CODE(status));
|
||||
printf(" Initializing modules:");
|
||||
for (i = 0; i < NUM_BOOT_MODULES; i++) {
|
||||
printf(" %s", boot_modules[i]->name);
|
||||
if (boot_modules[i]->init != NULL)
|
||||
boot_modules[i]->init();
|
||||
}
|
||||
putchar('\n');
|
||||
|
||||
/* Determine the devpath of our image so we can prefer it. */
|
||||
status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&boot_image);
|
||||
status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&img);
|
||||
imgpath = NULL;
|
||||
if (status == EFI_SUCCESS) {
|
||||
text = efi_devpath_name(boot_image->FilePath);
|
||||
printf(" Load Path: %S\n", text);
|
||||
efi_setenv_freebsd_wcs("Boot1Path", text);
|
||||
efi_free_devpath_name(text);
|
||||
text = efi_devpath_name(img->FilePath);
|
||||
if (text != NULL) {
|
||||
printf(" Load Path: %S\n", text);
|
||||
efi_setenv_freebsd_wcs("Boot1Path", text);
|
||||
efi_free_devpath_name(text);
|
||||
}
|
||||
|
||||
status = BS->HandleProtocol(boot_image->DeviceHandle, &DevicePathGUID,
|
||||
status = BS->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
|
||||
(void **)&imgpath);
|
||||
if (status != EFI_SUCCESS) {
|
||||
DPRINTF("Failed to get image DevicePath (%lu)\n",
|
||||
EFI_ERROR_CODE(status));
|
||||
} else {
|
||||
text = efi_devpath_name(imgpath);
|
||||
printf(" Load Device: %S\n", text);
|
||||
efi_setenv_freebsd_wcs("Boot1Dev", text);
|
||||
efi_free_devpath_name(text);
|
||||
if (text != NULL) {
|
||||
printf(" Load Device: %S\n", text);
|
||||
efi_setenv_freebsd_wcs("Boot1Dev", text);
|
||||
efi_free_devpath_name(text);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* The loaded image device path ends with a partition, then a
|
||||
* file path. Trim them both to get the actual disk.
|
||||
*/
|
||||
if ((imgprefix = efi_devpath_trim(imgpath)) == NULL ||
|
||||
(imgprefix = efi_devpath_trim(imgprefix)) == NULL) {
|
||||
panic("Couldn't trim device path");
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the block cache. Set the upper limit.
|
||||
*/
|
||||
bcache_init(32768, 512);
|
||||
|
||||
printf("\n Initializing modules:");
|
||||
|
||||
for (i = 0; efi_drivers[i] != NULL; i++) {
|
||||
printf(" %s", efi_drivers[i]->name);
|
||||
if (efi_drivers[i]->init != NULL)
|
||||
efi_drivers[i]->init();
|
||||
/* Get all the device handles */
|
||||
hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
|
||||
handles = malloc(hsize);
|
||||
if (handles == NULL) {
|
||||
printf("Failed to allocate %d handles\n", NUM_HANDLES_INIT);
|
||||
}
|
||||
|
||||
for (i = 0; devsw[i] != NULL; i++) {
|
||||
if (devsw[i]->dv_init != NULL) {
|
||||
printf(" %s", devsw[i]->dv_name);
|
||||
(devsw[i]->dv_init)();
|
||||
}
|
||||
}
|
||||
status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
|
||||
&hsize, handles);
|
||||
switch (status) {
|
||||
case EFI_SUCCESS:
|
||||
break;
|
||||
case EFI_BUFFER_TOO_SMALL:
|
||||
free(handles);
|
||||
handles = malloc(hsize);
|
||||
if (handles == NULL)
|
||||
efi_panic(EFI_OUT_OF_RESOURCES, "Failed to allocate %d handles\n",
|
||||
NUM_HANDLES_INIT);
|
||||
status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
|
||||
NULL, &hsize, handles);
|
||||
if (status != EFI_SUCCESS)
|
||||
efi_panic(status, "Failed to get device handles\n");
|
||||
break;
|
||||
default:
|
||||
efi_panic(status, "Failed to get device handles\n");
|
||||
break;
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
/* Scan all partitions, probing with all modules. */
|
||||
nhandles = hsize / sizeof(*handles);
|
||||
printf(" Probing %zu block devices...", nhandles);
|
||||
DPRINTF("\n");
|
||||
|
||||
for (i = 0; i < nhandles; i++)
|
||||
probe_handle_status(handles[i], imgpath);
|
||||
printf(" done\n");
|
||||
|
||||
/* Status summary. */
|
||||
for (i = 0; i < NUM_BOOT_MODULES; i++) {
|
||||
printf(" ");
|
||||
boot_modules[i]->status();
|
||||
}
|
||||
|
||||
try_boot();
|
||||
|
||||
@ -718,6 +530,25 @@ main(int argc __unused, CHAR16 *argv[] __unused)
|
||||
efi_panic(EFI_LOAD_ERROR, "No bootable partitions found!");
|
||||
}
|
||||
|
||||
/*
|
||||
* add_device adds a device to the passed devinfo list.
|
||||
*/
|
||||
void
|
||||
add_device(dev_info_t **devinfop, dev_info_t *devinfo)
|
||||
{
|
||||
dev_info_t *dev;
|
||||
|
||||
if (*devinfop == NULL) {
|
||||
*devinfop = devinfo;
|
||||
return;
|
||||
}
|
||||
|
||||
for (dev = *devinfop; dev->next != NULL; dev = dev->next)
|
||||
;
|
||||
|
||||
dev->next = devinfo;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK. We totally give up. Exit back to EFI with a sensible status so
|
||||
* it can try the next option on the list.
|
||||
@ -725,13 +556,28 @@ main(int argc __unused, CHAR16 *argv[] __unused)
|
||||
static void
|
||||
efi_panic(EFI_STATUS s, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
|
||||
printf("panic: ");
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
printf("\n");
|
||||
printf("panic: ");
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
printf("\n");
|
||||
|
||||
BS->Exit(IH, s, 0, NULL);
|
||||
BS->Exit(IH, s, 0, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
putchar(int c)
|
||||
{
|
||||
CHAR16 buf[2];
|
||||
|
||||
if (c == '\n') {
|
||||
buf[0] = '\r';
|
||||
buf[1] = 0;
|
||||
ST->ConOut->OutputString(ST->ConOut, buf);
|
||||
}
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
ST->ConOut->OutputString(ST->ConOut, buf);
|
||||
}
|
||||
|
109
sys/boot/efi/boot1/boot_module.h
Normal file
109
sys/boot/efi/boot1/boot_module.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Eric McCorkle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BOOT_MODULE_H_
|
||||
#define _BOOT_MODULE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
#include <eficonsctl.h>
|
||||
|
||||
#ifdef EFI_DEBUG
|
||||
#define DPRINTF(fmt, args...) printf(fmt, ##args)
|
||||
#define DSTALL(d) BS->Stall(d)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...) {}
|
||||
#define DSTALL(d) {}
|
||||
#endif
|
||||
|
||||
/* EFI device info */
|
||||
typedef struct dev_info
|
||||
{
|
||||
EFI_BLOCK_IO *dev;
|
||||
EFI_DEVICE_PATH *devpath;
|
||||
EFI_HANDLE *devhandle;
|
||||
void *devdata;
|
||||
BOOLEAN preferred;
|
||||
struct dev_info *next;
|
||||
} dev_info_t;
|
||||
|
||||
/*
|
||||
* A boot loader module.
|
||||
*
|
||||
* This is a standard interface for filesystem modules in the EFI system.
|
||||
*/
|
||||
typedef struct boot_module_t
|
||||
{
|
||||
const char *name;
|
||||
|
||||
/* init is the optional initialiser for the module. */
|
||||
void (*init)(void);
|
||||
|
||||
/*
|
||||
* probe checks to see if the module can handle dev.
|
||||
*
|
||||
* Return codes:
|
||||
* EFI_SUCCESS = The module can handle the device.
|
||||
* EFI_NOT_FOUND = The module can not handle the device.
|
||||
* Other = The module encountered an error.
|
||||
*/
|
||||
EFI_STATUS (*probe)(dev_info_t* dev);
|
||||
|
||||
/*
|
||||
* load should select the best out of a set of devices that probe
|
||||
* indicated were loadable and load the specified file.
|
||||
*
|
||||
* Return codes:
|
||||
* EFI_SUCCESS = The module can handle the device.
|
||||
* EFI_NOT_FOUND = The module can not handle the device.
|
||||
* Other = The module encountered an error.
|
||||
*/
|
||||
EFI_STATUS (*load)(const char *filepath, dev_info_t *devinfo,
|
||||
void **buf, size_t *bufsize);
|
||||
|
||||
/* status outputs information about the probed devices. */
|
||||
void (*status)(void);
|
||||
|
||||
/* valid devices as found by probe. */
|
||||
dev_info_t *(*devices)(void);
|
||||
} boot_module_t;
|
||||
|
||||
/* Standard boot modules. */
|
||||
#ifdef EFI_UFS_BOOT
|
||||
extern const boot_module_t ufs_module;
|
||||
#endif
|
||||
#ifdef EFI_ZFS_BOOT
|
||||
extern const boot_module_t zfs_module;
|
||||
#endif
|
||||
|
||||
/* Functions available to modules. */
|
||||
extern void add_device(dev_info_t **devinfop, dev_info_t *devinfo);
|
||||
extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
|
||||
#endif
|
185
sys/boot/efi/boot1/ufs_module.c
Normal file
185
sys/boot/efi/boot1/ufs_module.c
Normal file
@ -0,0 +1,185 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Robert Nordier
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2001 Robert Drehmel
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2014 Nathan Whitehorn
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2015 Eric McCorkle
|
||||
* All rights reverved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
#include <efi.h>
|
||||
|
||||
#include "boot_module.h"
|
||||
|
||||
static dev_info_t *devinfo;
|
||||
static dev_info_t *devices;
|
||||
|
||||
static int
|
||||
dskread(void *buf, u_int64_t lba, int nblk)
|
||||
{
|
||||
int size;
|
||||
EFI_STATUS status;
|
||||
|
||||
lba = lba / (devinfo->dev->Media->BlockSize / DEV_BSIZE);
|
||||
size = nblk * DEV_BSIZE;
|
||||
|
||||
status = devinfo->dev->ReadBlocks(devinfo->dev,
|
||||
devinfo->dev->Media->MediaId, lba, size, buf);
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
DPRINTF("dskread: failed dev: %p, id: %u, lba: %ju, size: %d, "
|
||||
"status: %lu\n", devinfo->dev,
|
||||
devinfo->dev->Media->MediaId, (uintmax_t)lba, size,
|
||||
EFI_ERROR_CODE(status));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#include "ufsread.c"
|
||||
|
||||
static struct dmadat __dmadat;
|
||||
|
||||
static int
|
||||
init_dev(dev_info_t* dev)
|
||||
{
|
||||
|
||||
devinfo = dev;
|
||||
dmadat = &__dmadat;
|
||||
|
||||
return fsread(0, NULL, 0);
|
||||
}
|
||||
|
||||
static EFI_STATUS
|
||||
probe(dev_info_t* dev)
|
||||
{
|
||||
|
||||
if (init_dev(dev) < 0)
|
||||
return (EFI_UNSUPPORTED);
|
||||
|
||||
add_device(&devices, dev);
|
||||
|
||||
return (EFI_SUCCESS);
|
||||
}
|
||||
|
||||
static EFI_STATUS
|
||||
load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize)
|
||||
{
|
||||
ufs_ino_t ino;
|
||||
EFI_STATUS status;
|
||||
size_t size;
|
||||
ssize_t read;
|
||||
void *buf;
|
||||
|
||||
#ifdef EFI_DEBUG
|
||||
{
|
||||
CHAR16 *text = efi_devpath_name(dev->devpath);
|
||||
DPRINTF("Loading '%s' from %S\n", filepath, text);
|
||||
efi_free_devpath_name(text);
|
||||
}
|
||||
#endif
|
||||
if (init_dev(dev) < 0) {
|
||||
DPRINTF("Failed to init device\n");
|
||||
return (EFI_UNSUPPORTED);
|
||||
}
|
||||
|
||||
if ((ino = lookup(filepath)) == 0) {
|
||||
DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath);
|
||||
return (EFI_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) {
|
||||
printf("Failed to read size of '%s' ino: %d\n", filepath, ino);
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if ((status = BS->AllocatePool(EfiLoaderData, size, &buf)) !=
|
||||
EFI_SUCCESS) {
|
||||
printf("Failed to allocate read buffer %zu for '%s' (%lu)\n",
|
||||
size, filepath, EFI_ERROR_CODE(status));
|
||||
return (status);
|
||||
}
|
||||
|
||||
read = fsread(ino, buf, size);
|
||||
if ((size_t)read != size) {
|
||||
printf("Failed to read '%s' (%zd != %zu)\n", filepath, read,
|
||||
size);
|
||||
(void)BS->FreePool(buf);
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
DPRINTF("Load complete\n");
|
||||
|
||||
*bufp = buf;
|
||||
*bufsize = size;
|
||||
|
||||
return (EFI_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
status(void)
|
||||
{
|
||||
int i;
|
||||
dev_info_t *dev;
|
||||
|
||||
for (dev = devices, i = 0; dev != NULL; dev = dev->next, i++)
|
||||
;
|
||||
|
||||
printf("%s found ", ufs_module.name);
|
||||
switch (i) {
|
||||
case 0:
|
||||
printf("no partitions\n");
|
||||
break;
|
||||
case 1:
|
||||
printf("%d partition\n", i);
|
||||
break;
|
||||
default:
|
||||
printf("%d partitions\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
static dev_info_t *
|
||||
_devices(void)
|
||||
{
|
||||
|
||||
return (devices);
|
||||
}
|
||||
|
||||
const boot_module_t ufs_module =
|
||||
{
|
||||
.name = "UFS",
|
||||
.probe = probe,
|
||||
.load = load,
|
||||
.status = status,
|
||||
.devices = _devices
|
||||
};
|
248
sys/boot/efi/boot1/zfs_module.c
Normal file
248
sys/boot/efi/boot1/zfs_module.c
Normal file
@ -0,0 +1,248 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Eric McCorkle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
#include <efi.h>
|
||||
|
||||
#include "boot_module.h"
|
||||
|
||||
#include "libzfs.h"
|
||||
#include "zfsimpl.c"
|
||||
|
||||
static dev_info_t *devices;
|
||||
|
||||
uint64_t
|
||||
ldi_get_size(void *priv)
|
||||
{
|
||||
dev_info_t *devinfo = priv;
|
||||
|
||||
return (devinfo->dev->Media->BlockSize *
|
||||
(devinfo->dev->Media->LastBlock + 1));
|
||||
}
|
||||
|
||||
static int
|
||||
vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
|
||||
{
|
||||
dev_info_t *devinfo;
|
||||
uint64_t lba;
|
||||
size_t size, remainder, rb_size, blksz;
|
||||
char *bouncebuf = NULL, *rb_buf;
|
||||
EFI_STATUS status;
|
||||
|
||||
devinfo = (dev_info_t *)priv;
|
||||
lba = off / devinfo->dev->Media->BlockSize;
|
||||
remainder = off % devinfo->dev->Media->BlockSize;
|
||||
|
||||
rb_buf = buf;
|
||||
rb_size = bytes;
|
||||
|
||||
/*
|
||||
* If we have remainder from off, we need to add remainder part.
|
||||
* Since buffer must be multiple of the BlockSize, round it all up.
|
||||
*/
|
||||
size = roundup2(bytes + remainder, devinfo->dev->Media->BlockSize);
|
||||
blksz = size;
|
||||
if (remainder != 0 || size != bytes) {
|
||||
rb_size = devinfo->dev->Media->BlockSize;
|
||||
bouncebuf = malloc(rb_size);
|
||||
if (bouncebuf == NULL) {
|
||||
printf("vdev_read: out of memory\n");
|
||||
return (-1);
|
||||
}
|
||||
rb_buf = bouncebuf;
|
||||
blksz = rb_size - remainder;
|
||||
}
|
||||
|
||||
while (bytes > 0) {
|
||||
status = devinfo->dev->ReadBlocks(devinfo->dev,
|
||||
devinfo->dev->Media->MediaId, lba, rb_size, rb_buf);
|
||||
if (EFI_ERROR(status))
|
||||
goto error;
|
||||
if (bytes < blksz)
|
||||
blksz = bytes;
|
||||
if (bouncebuf != NULL)
|
||||
memcpy(buf, rb_buf + remainder, blksz);
|
||||
buf = (void *)((uintptr_t)buf + blksz);
|
||||
bytes -= blksz;
|
||||
lba++;
|
||||
remainder = 0;
|
||||
blksz = rb_size;
|
||||
}
|
||||
|
||||
free(bouncebuf);
|
||||
return (0);
|
||||
|
||||
error:
|
||||
free(bouncebuf);
|
||||
DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %ju, size: %zu,"
|
||||
" rb_size: %zu, status: %lu\n", devinfo->dev,
|
||||
devinfo->dev->Media->MediaId, (uintmax_t)lba, bytes, rb_size,
|
||||
EFI_ERROR_CODE(status));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static EFI_STATUS
|
||||
probe(dev_info_t *dev)
|
||||
{
|
||||
spa_t *spa;
|
||||
dev_info_t *tdev;
|
||||
EFI_STATUS status;
|
||||
|
||||
/* ZFS consumes the dev on success so we need a copy. */
|
||||
if ((status = BS->AllocatePool(EfiLoaderData, sizeof(*dev),
|
||||
(void**)&tdev)) != EFI_SUCCESS) {
|
||||
DPRINTF("Failed to allocate tdev (%lu)\n",
|
||||
EFI_ERROR_CODE(status));
|
||||
return (status);
|
||||
}
|
||||
memcpy(tdev, dev, sizeof(*dev));
|
||||
|
||||
if (vdev_probe(vdev_read, tdev, &spa) != 0) {
|
||||
(void)BS->FreePool(tdev);
|
||||
return (EFI_UNSUPPORTED);
|
||||
}
|
||||
|
||||
dev->devdata = spa;
|
||||
add_device(&devices, dev);
|
||||
|
||||
return (EFI_SUCCESS);
|
||||
}
|
||||
|
||||
static EFI_STATUS
|
||||
load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize)
|
||||
{
|
||||
spa_t *spa;
|
||||
struct zfsmount zfsmount;
|
||||
dnode_phys_t dn;
|
||||
struct stat st;
|
||||
int err;
|
||||
void *buf;
|
||||
EFI_STATUS status;
|
||||
|
||||
spa = devinfo->devdata;
|
||||
|
||||
#ifdef EFI_DEBUG
|
||||
{
|
||||
CHAR16 *text = efi_devpath_name(devinfo->devpath);
|
||||
DPRINTF("load: '%s' spa: '%s', devpath: %S\n", filepath,
|
||||
spa->spa_name, text);
|
||||
efi_free_devpath_name(text);
|
||||
}
|
||||
#endif
|
||||
if ((err = zfs_spa_init(spa)) != 0) {
|
||||
DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err);
|
||||
return (EFI_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) {
|
||||
DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err);
|
||||
return (EFI_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) {
|
||||
if (err == ENOENT) {
|
||||
DPRINTF("Failed to find '%s' on pool '%s' (%d)\n",
|
||||
filepath, spa->spa_name, err);
|
||||
return (EFI_NOT_FOUND);
|
||||
}
|
||||
printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath,
|
||||
spa->spa_name, err);
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) {
|
||||
printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath,
|
||||
spa->spa_name, err);
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if ((status = BS->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf))
|
||||
!= EFI_SUCCESS) {
|
||||
printf("Failed to allocate load buffer %jd for pool '%s' for '%s' "
|
||||
"(%lu)\n", (intmax_t)st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status));
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if ((err = dnode_read(spa, &dn, 0, buf, st.st_size)) != 0) {
|
||||
printf("Failed to read node from %s (%d)\n", spa->spa_name,
|
||||
err);
|
||||
(void)BS->FreePool(buf);
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
*bufsize = st.st_size;
|
||||
*bufp = buf;
|
||||
|
||||
return (EFI_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
status(void)
|
||||
{
|
||||
spa_t *spa;
|
||||
|
||||
spa = STAILQ_FIRST(&zfs_pools);
|
||||
if (spa == NULL) {
|
||||
printf("%s found no pools\n", zfs_module.name);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s found the following pools:", zfs_module.name);
|
||||
STAILQ_FOREACH(spa, &zfs_pools, spa_link)
|
||||
printf(" %s", spa->spa_name);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
|
||||
zfs_init();
|
||||
}
|
||||
|
||||
static dev_info_t *
|
||||
_devices(void)
|
||||
{
|
||||
|
||||
return (devices);
|
||||
}
|
||||
|
||||
const boot_module_t zfs_module =
|
||||
{
|
||||
.name = "ZFS",
|
||||
.init = init,
|
||||
.probe = probe,
|
||||
.load = load,
|
||||
.status = status,
|
||||
.devices = _devices
|
||||
};
|
@ -1,8 +1,8 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
.include <bsd.init.mk>
|
||||
|
||||
.PATH: ${.CURDIR}/../../common
|
||||
.PATH: ${LDRSRC}
|
||||
|
||||
LIB= efi_fdt
|
||||
INTERNALLIB=
|
||||
@ -18,20 +18,13 @@ CFLAGS+= -msoft-float
|
||||
.endif
|
||||
|
||||
# EFI library headers
|
||||
CFLAGS+= -I${.CURDIR}/../include
|
||||
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
|
||||
CFLAGS+= -I${EFISRC}/include
|
||||
CFLAGS+= -I${EFISRC}/include/${MACHINE}
|
||||
|
||||
# libfdt headers
|
||||
CFLAGS+= -I${.CURDIR}/../../fdt
|
||||
CFLAGS+= -I${FDTSRC}
|
||||
|
||||
# Pick up the bootstrap header for some interface items
|
||||
CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../../.. -I.
|
||||
|
||||
machine: .NOMETA
|
||||
ln -sf ${.CURDIR}/../../../${MACHINE}/include machine
|
||||
|
||||
CLEANFILES+= machine
|
||||
CFLAGS+= -I${LDRSRC}
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
||||
beforedepend ${OBJS}: machine
|
||||
|
@ -82,7 +82,7 @@ EFI_HANDLE efi_devpath_handle(EFI_DEVICE_PATH *);
|
||||
EFI_DEVICE_PATH *efi_devpath_last_node(EFI_DEVICE_PATH *);
|
||||
EFI_DEVICE_PATH *efi_devpath_trim(EFI_DEVICE_PATH *);
|
||||
bool efi_devpath_match(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *);
|
||||
int efi_devpath_is_prefix(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *);
|
||||
bool efi_devpath_is_prefix(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *);
|
||||
CHAR16 *efi_devpath_name(EFI_DEVICE_PATH *);
|
||||
void efi_free_devpath_name(CHAR16 *);
|
||||
|
||||
|
@ -1,19 +1,17 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
.include <bsd.init.mk>
|
||||
|
||||
.if ${MK_FORTH} != "no"
|
||||
CFLAGS+= -DBOOT_FORTH
|
||||
.include "../../ficl.mk"
|
||||
.include "${BOOTSRC}/ficl.mk"
|
||||
.endif
|
||||
|
||||
LIB= efi
|
||||
INTERNALLIB=
|
||||
WARNS?= 2
|
||||
|
||||
SRCS= delay.c devpath.c efi_console.c efichar.c efinet.c efipart.c env.c \
|
||||
errno.c handles.c wchar.c libefi.c efi_driver_utils.c efizfs.c \
|
||||
devicename.c efi_main.c
|
||||
SRCS= delay.c devpath.c efi_console.c efichar.c efinet.c efipart.c env.c errno.c \
|
||||
handles.c wchar.c libefi.c efi_driver_utils.c efizfs.c devicename.c
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
|
||||
SRCS+= time.c
|
||||
@ -36,17 +34,15 @@ CFLAGS+= -mgeneral-regs-only
|
||||
.if ${MACHINE_ARCH} == "amd64"
|
||||
CFLAGS+= -fPIC -mno-red-zone
|
||||
.endif
|
||||
CFLAGS+= -I${.CURDIR}/../include
|
||||
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
|
||||
CFLAGS+= -I${EFIINC}
|
||||
CFLAGS+= -I${EFIINCMD}
|
||||
.if ${MK_ZFS} != "no"
|
||||
CFLAGS+= -I${.CURDIR}/../../zfs
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs
|
||||
CFLAGS+= -I${.CURDIR}/../../../crypto/skein
|
||||
CFLAGS+= -I${ZFSSRC}
|
||||
CFLAGS+= -DEFI_ZFS_BOOT
|
||||
.endif
|
||||
|
||||
# Pick up the bootstrap header for some interface items
|
||||
CFLAGS+= -I${.CURDIR}/../../common
|
||||
CFLAGS+= -I${LDRSRC}
|
||||
|
||||
# Handle FreeBSD specific %b and %D printf format specifiers
|
||||
CFLAGS+= ${FORMAT_EXTENSIONS}
|
||||
|
@ -167,13 +167,13 @@ efi_devpath_match(EFI_DEVICE_PATH *devpath1, EFI_DEVICE_PATH *devpath2)
|
||||
return (true);
|
||||
}
|
||||
|
||||
int
|
||||
bool
|
||||
efi_devpath_is_prefix(EFI_DEVICE_PATH *prefix, EFI_DEVICE_PATH *path)
|
||||
{
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
if (prefix == NULL || path == NULL)
|
||||
return (0);
|
||||
return (false);
|
||||
|
||||
while (1) {
|
||||
if (IsDevicePathEnd(prefix))
|
||||
@ -181,17 +181,17 @@ efi_devpath_is_prefix(EFI_DEVICE_PATH *prefix, EFI_DEVICE_PATH *path)
|
||||
|
||||
if (DevicePathType(prefix) != DevicePathType(path) ||
|
||||
DevicePathSubType(prefix) != DevicePathSubType(path))
|
||||
return (0);
|
||||
return (false);
|
||||
|
||||
len = DevicePathNodeLength(prefix);
|
||||
if (len != DevicePathNodeLength(path))
|
||||
return (0);
|
||||
return (false);
|
||||
|
||||
if (memcmp(prefix, path, (size_t)len) != 0)
|
||||
return (0);
|
||||
if (memcmp(prefix, path, len) != 0)
|
||||
return (false);
|
||||
|
||||
prefix = NextDevicePathNode(prefix);
|
||||
path = NextDevicePathNode(path);
|
||||
}
|
||||
return (1);
|
||||
return (true);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user