9
0
Fork 0

Merge branch 'for-next/omap'

Conflicts:
	Makefile
This commit is contained in:
Sascha Hauer 2012-10-03 21:11:48 +02:00
commit bee8dddbfc
22 changed files with 403 additions and 144 deletions

1
.gitignore vendored
View File

@ -34,6 +34,7 @@ barebox.bin
barebox.srec
barebox.netx
barebox.s5p
barebox.spi
barebox.ubl
barebox.uimage
barebox.map

View File

@ -1032,7 +1032,7 @@ CLEAN_FILES += barebox System.map include/generated/barebox_default_env.h \
.tmp_kallsyms* barebox_default_env* barebox.ldr \
scripts/bareboxenv-target barebox-flash-image \
Doxyfile.version barebox.srec barebox.s5p barebox.ubl \
barebox.uimage
barebox.uimage barebox.spi
# Directories & files removed with 'make mrproper'
MRPROPER_DIRS += include/config include2 usr/include

View File

@ -58,6 +58,7 @@ config ARCH_NOMADIK
config ARCH_OMAP
bool "TI OMAP"
select HAS_DEBUG_LL
select GPIOLIB
config ARCH_PXA
bool "Intel/Marvell PXA based"

View File

@ -217,6 +217,17 @@ KBUILD_TARGET := barebox.ubl
KBUILD_IMAGE := barebox.ubl
endif
quiet_cmd_am35xx_spi_image = SPI-IMG $@
cmd_am35xx_spi_image = scripts/mk-am35xx-spi-image $< > $@
barebox.spi: $(KBUILD_BINARY) FORCE
$(call if_changed,am35xx_spi_image)
ifeq ($(CONFIG_OMAP_BUILD_SPI),y)
KBUILD_TARGET := barebox.spi
KBUILD_IMAGE := barebox.spi
endif
pbl := arch/arm/pbl
zbarebox.S zbarebox.bin zbarebox: barebox.bin
$(Q)$(MAKE) $(build)=$(pbl) $(pbl)/$@

View File

@ -118,9 +118,9 @@ static int pcm049_devices_init(void)
#ifdef CONFIG_PARTITION
devfs_add_partition("nand0", 0x00000, SZ_128K, DEVFS_PARTITION_FIXED, "xload_raw");
dev_add_bb_dev("xload_raw", "xload");
devfs_add_partition("nand0", SZ_128K, SZ_256K, DEVFS_PARTITION_FIXED, "self_raw");
devfs_add_partition("nand0", SZ_128K, SZ_512K, DEVFS_PARTITION_FIXED, "self_raw");
dev_add_bb_dev("self_raw", "self0");
devfs_add_partition("nand0", SZ_128K + SZ_256K, SZ_128K, DEVFS_PARTITION_FIXED, "env_raw");
devfs_add_partition("nand0", SZ_128K + SZ_512K, SZ_128K, DEVFS_PARTITION_FIXED, "env_raw");
dev_add_bb_dev("env_raw", "env0");
#endif

View File

@ -40,7 +40,7 @@ autoboot_timeout=3
bootargs="console=ttyO2,115200"
nand_parts="128k(xload)ro,256k(barebox),128k(bareboxenv),2M(kernel),-(root)"
nand_parts="128k(xload)ro,512k(barebox),128k(bareboxenv),4M(kernel),-(root)"
rootfs_mtdblock_nand=4
# set a fancy prompt (if support is compiled in)

View File

@ -70,7 +70,7 @@ bootargs="$bootargs omapdss.def_disp=pd050vl1"
#bootargs="$bootargs omapdss.def_disp=pd104slf"
#bootargs="$bootargs omapdss.def_disp=pm070wl4"
nand_parts="512k(x-loader)ro,1920k(barebox),128k(bareboxenv),4M(kernel),-(root)"
nand_parts="128k(x-loader)ro,512k(barebox),128k(bareboxenv),4M(kernel),-(root)"
nand_device=omap2-nand.0
rootfs_mtdblock_nand=4

View File

@ -422,13 +422,13 @@ device_initcall(pcaal1_init_devices);
static int pcaal1_late_init(void)
{
#ifdef CONFIG_PARTITION
devfs_add_partition("nand0", 0x00000, 0x80000, DEVFS_PARTITION_FIXED, "x-loader");
devfs_add_partition("nand0", 0x00000, SZ_128K, DEVFS_PARTITION_FIXED, "x-loader");
dev_add_bb_dev("self_raw", "x_loader0");
devfs_add_partition("nand0", 0x80000, 0x1e0000, DEVFS_PARTITION_FIXED, "self_raw");
devfs_add_partition("nand0", SZ_128K, SZ_512K, DEVFS_PARTITION_FIXED, "self_raw");
dev_add_bb_dev("self_raw", "self0");
devfs_add_partition("nand0", 0x260000, 0x20000, DEVFS_PARTITION_FIXED, "env_raw");
devfs_add_partition("nand0", SZ_128K + SZ_512K, SZ_128K, DEVFS_PARTITION_FIXED, "env_raw");
dev_add_bb_dev("env_raw", "env0");
#endif
return 0;

View File

@ -39,7 +39,7 @@ autoboot_timeout=3
bootargs="console=ttyO2,115200"
nand_parts="128k(xload)ro,256k(barebox),128k(bareboxenv),4M(kernel),-(root)"
nand_parts="128k(xload)ro,512k(barebox),128k(bareboxenv),4M(kernel),-(root)"
rootfs_mtdblock_nand=4
# set a fancy prompt (if support is compiled in)

View File

@ -136,10 +136,10 @@ static int pcaaxl2_devices_init(void)
devfs_add_partition("nand0", 0x00000, SZ_128K,
DEVFS_PARTITION_FIXED, "xload_raw");
dev_add_bb_dev("xload_raw", "xload");
devfs_add_partition("nand0", SZ_128K, SZ_256K,
devfs_add_partition("nand0", SZ_128K, SZ_512K,
DEVFS_PARTITION_FIXED, "self_raw");
dev_add_bb_dev("self_raw", "self0");
devfs_add_partition("nand0", SZ_128K + SZ_256K, SZ_128K,
devfs_add_partition("nand0", SZ_128K + SZ_512K, SZ_128K,
DEVFS_PARTITION_FIXED, "env_raw");
dev_add_bb_dev("env_raw", "env0");
#endif

View File

@ -52,20 +52,7 @@ config ARCH_OMAP4
endchoice
### Generic Clock configurations to be enabled by Mach - invisible to enable.
config OMAP_CLOCK_UART
bool
config OMAP_CLOCK_UART2
bool
config OMAP_CLOCK_UART3
bool
config OMAP_CLOCK_I2C
bool
# Blind enable all possible clocks.. think twice before you do this.
config OMAP_CLOCK_ALL
bool
config OMAP_CLOCK_SOURCE_S32K
bool
@ -91,6 +78,13 @@ config OMAP_BUILD_IFT
prompt "build ift binary"
bool
config OMAP_BUILD_SPI
prompt "build SPI binary"
bool
help
Say Y here if you want to build an barebox.spi image as used
on the AM35xx chips when booting form SPI NOR flash.
config ARCH_TEXT_BASE
hex
default 0x80e80000 if MACH_OMAP343xSDP
@ -110,14 +104,12 @@ choice
config MACH_OMAP343xSDP
bool "Texas Instrument's SDP343x"
select OMAP_CLOCK_ALL
depends on ARCH_OMAP3
help
Say Y here if you are using SDP343x platform
config MACH_BEAGLE
bool "Texas Instrument's Beagle Board"
select OMAP_CLOCK_ALL
select HAVE_NOSHELL
depends on ARCH_OMAP3
help
@ -125,7 +117,6 @@ config MACH_BEAGLE
config MACH_OMAP3EVM
bool "Texas Instrument's OMAP3 EVM"
select OMAP_CLOCK_ALL
select HAVE_NOSHELL
depends on ARCH_OMAP3
help
@ -150,7 +141,6 @@ config MACH_PCM049
config MACH_PCAAL1
bool "Phytec phyCARD-A-L1"
select OMAP_CLOCK_ALL
select HAVE_NOSHELL
depends on ARCH_OMAP3
help

View File

@ -36,11 +36,10 @@
* published by the Free Software Foundation.
*/
#include <common.h>
#include <mach/gpio.h>
#include <io.h>
#include <errno.h>
#ifdef CONFIG_ARCH_OMAP3
#include <gpio.h>
#include <init.h>
#define OMAP_GPIO_OE 0x0034
#define OMAP_GPIO_DATAIN 0x0038
@ -48,129 +47,115 @@
#define OMAP_GPIO_CLEARDATAOUT 0x0090
#define OMAP_GPIO_SETDATAOUT 0x0094
static void __iomem *gpio_bank[] = {
(void *)0x48310000,
(void *)0x49050000,
(void *)0x49052000,
(void *)0x49054000,
(void *)0x49056000,
(void *)0x49058000,
struct omap_gpio_chip {
void __iomem *base;
struct gpio_chip chip;
};
#endif
#ifdef CONFIG_ARCH_OMAP4
#define OMAP_GPIO_OE 0x0134
#define OMAP_GPIO_DATAIN 0x0138
#define OMAP_GPIO_DATAOUT 0x013c
#define OMAP_GPIO_CLEARDATAOUT 0x0190
#define OMAP_GPIO_SETDATAOUT 0x0194
static void __iomem *gpio_bank[] = {
(void *)0x4a310000,
(void *)0x48055000,
(void *)0x48057000,
(void *)0x48059000,
(void *)0x4805b000,
(void *)0x4805d000,
};
#endif
static inline void __iomem *get_gpio_base(int gpio)
{
return gpio_bank[gpio >> 5];
}
static inline int get_gpio_index(int gpio)
static inline int omap_get_gpio_index(int gpio)
{
return gpio & 0x1f;
}
static inline int gpio_valid(int gpio)
static void omap_gpio_set_value(struct gpio_chip *chip,
unsigned gpio, int value)
{
if (gpio < 0)
return -1;
if (gpio / 32 < ARRAY_SIZE(gpio_bank))
return 0;
return -1;
}
static int check_gpio(int gpio)
{
if (gpio_valid(gpio) < 0) {
printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
return -1;
}
return 0;
}
void gpio_set_value(unsigned gpio, int value)
{
void __iomem *reg;
struct omap_gpio_chip *omapgpio =
container_of(chip, struct omap_gpio_chip, chip);
void __iomem *base = omapgpio->base;
u32 l = 0;
if (check_gpio(gpio) < 0)
return;
reg = get_gpio_base(gpio);
if (value)
reg += OMAP_GPIO_SETDATAOUT;
base += OMAP_GPIO_SETDATAOUT;
else
reg += OMAP_GPIO_CLEARDATAOUT;
l = 1 << get_gpio_index(gpio);
base += OMAP_GPIO_CLEARDATAOUT;
__raw_writel(l, reg);
l = 1 << omap_get_gpio_index(gpio);
writel(l, base);
}
int gpio_direction_input(unsigned gpio)
static int omap_gpio_direction_input(struct gpio_chip *chip,
unsigned gpio)
{
void __iomem *reg;
struct omap_gpio_chip *omapgpio =
container_of(chip, struct omap_gpio_chip, chip);
void __iomem *base = omapgpio->base;
u32 val;
if (check_gpio(gpio) < 0)
return -EINVAL;
base += OMAP_GPIO_OE;
reg = get_gpio_base(gpio);
reg += OMAP_GPIO_OE;
val = __raw_readl(reg);
val |= 1 << get_gpio_index(gpio);
__raw_writel(val, reg);
val = readl(base);
val |= 1 << omap_get_gpio_index(gpio);
writel(val, base);
return 0;
}
int gpio_direction_output(unsigned gpio, int value)
static int omap_gpio_direction_output(struct gpio_chip *chip,
unsigned gpio, int value)
{
void __iomem *reg;
struct omap_gpio_chip *omapgpio =
container_of(chip, struct omap_gpio_chip, chip);
void __iomem *base = omapgpio->base;
u32 val;
if (check_gpio(gpio) < 0)
return -EINVAL;
reg = get_gpio_base(gpio);
omap_gpio_set_value(chip, gpio, value);
gpio_set_value(gpio, value);
base += OMAP_GPIO_OE;
reg += OMAP_GPIO_OE;
val = __raw_readl(reg);
val &= ~(1 << get_gpio_index(gpio));
__raw_writel(val, reg);
val = readl(base);
val &= ~(1 << omap_get_gpio_index(gpio));
writel(val, base);
return 0;
}
int gpio_get_value(unsigned gpio)
static int omap_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
void __iomem *reg;
struct omap_gpio_chip *omapgpio =
container_of(chip, struct omap_gpio_chip, chip);
void __iomem *base = omapgpio->base;
if (check_gpio(gpio) < 0)
return -EINVAL;
reg = get_gpio_base(gpio);
base += OMAP_GPIO_DATAIN;
reg += OMAP_GPIO_DATAIN;
return (readl(base) & (1 << omap_get_gpio_index(gpio))) != 0;
return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
}
static struct gpio_ops omap_gpio_ops = {
.direction_input = omap_gpio_direction_input,
.direction_output = omap_gpio_direction_output,
.get = omap_gpio_get_value,
.set = omap_gpio_set_value,
};
static int omap_gpio_probe(struct device_d *dev)
{
struct omap_gpio_chip *omapgpio;
omapgpio = xzalloc(sizeof(*omapgpio));
omapgpio->base = dev_request_mem_region(dev, 0);
omapgpio->chip.ops = &omap_gpio_ops;
omapgpio->chip.base = -1;
omapgpio->chip.ngpio = 32;
omapgpio->chip.dev = dev;
gpiochip_add(&omapgpio->chip);
dev_dbg(dev, "probed gpiochip%d with base %d\n",
dev->id, omapgpio->chip.base);
return 0;
}
static struct driver_d omap_gpio_driver = {
.name = "omap-gpio",
.probe = omap_gpio_probe,
};
static int omap_gpio_add(void)
{
register_driver(&omap_gpio_driver);
return 0;
}
coredevice_initcall(omap_gpio_add);

View File

@ -1,13 +1,11 @@
#ifndef _MACH_XLOAD_H
#define _MACH_XLOAD_H
void *omap_xload_boot_nand(int offset, int size);
void *omap_xload_boot_mmc(void);
enum omap_boot_src {
OMAP_BOOTSRC_UNKNOWN,
OMAP_BOOTSRC_MMC1,
OMAP_BOOTSRC_NAND,
OMAP_BOOTSRC_SPI1,
};
enum omap_boot_src omap3_bootsrc(void);

View File

@ -674,18 +674,6 @@ static void per_clocks_enable(void)
/* Enable the ICLK for 32K Sync Timer as its used in udelay */
sr32(CM_REG(ICLKEN_WKUP), 2, 1, 0x1);
#ifdef CONFIG_OMAP_CLOCK_UART
/* Enable UART1 clocks */
sr32(CM_REG(FCLKEN1_CORE), 13, 1, 0x1);
sr32(CM_REG(ICLKEN1_CORE), 13, 1, 0x1);
#endif
#ifdef CONFIG_OMAP_CLOCK_I2C
/* Turn on all 3 I2C clocks */
sr32(CM_REG(FCLKEN1_CORE), 15, 3, 0x7);
sr32(CM_REG(ICLKEN1_CORE), 15, 3, 0x7); /* I2C1,2,3 = on */
#endif
#ifdef CONFIG_OMAP_CLOCK_ALL
#define FCK_IVA2_ON 0x00000001
#define FCK_CORE1_ON 0x03fffe29
#define ICK_CORE1_ON 0x3ffffffb
@ -710,7 +698,7 @@ static void per_clocks_enable(void)
sr32(CM_REG(ICLKEN_CAM), 0, 32, ICK_CAM_ON);
sr32(CM_REG(FCLKEN_PER), 0, 32, FCK_PER_ON);
sr32(CM_REG(ICLKEN_PER), 0, 32, ICK_PER_ON);
#endif
/* Settle down my friend */
sdelay(1000);
}

View File

@ -515,3 +515,22 @@ const struct gpmc_config omap3_nand_cfg = {
.base = 0x28000000,
.size = GPMC_SIZE_16M,
};
static int omap3_gpio_init(void)
{
add_generic_device("omap-gpio", 0, NULL, 0x48310000,
0x100, IORESOURCE_MEM, NULL);
add_generic_device("omap-gpio", 1, NULL, 0x49050000,
0x100, IORESOURCE_MEM, NULL);
add_generic_device("omap-gpio", 2, NULL, 0x49052000,
0x100, IORESOURCE_MEM, NULL);
add_generic_device("omap-gpio", 3, NULL, 0x49054000,
0x100, IORESOURCE_MEM, NULL);
add_generic_device("omap-gpio", 4, NULL, 0x49056000,
0x100, IORESOURCE_MEM, NULL);
add_generic_device("omap-gpio", 5, NULL, 0x49058000,
0x100, IORESOURCE_MEM, NULL);
return 0;
}
coredevice_initcall(omap3_gpio_init);

View File

@ -572,3 +572,22 @@ const struct gpmc_config omap4_nand_cfg = {
.base = 0x28000000,
.size = GPMC_SIZE_16M,
};
static int omap4_gpio_init(void)
{
add_generic_device("omap-gpio", 0, NULL, 0x4a310100,
0x1000, IORESOURCE_MEM, NULL);
add_generic_device("omap-gpio", 1, NULL, 0x48055100,
0x1000, IORESOURCE_MEM, NULL);
add_generic_device("omap-gpio", 2, NULL, 0x48057100,
0x1000, IORESOURCE_MEM, NULL);
add_generic_device("omap-gpio", 3, NULL, 0x48059100,
0x1000, IORESOURCE_MEM, NULL);
add_generic_device("omap-gpio", 4, NULL, 0x4805b100,
0x1000, IORESOURCE_MEM, NULL);
add_generic_device("omap-gpio", 5, NULL, 0x4805d100,
0x1000, IORESOURCE_MEM, NULL);
return 0;
}
coredevice_initcall(omap4_gpio_init);

View File

@ -7,16 +7,65 @@
#include <fcntl.h>
#include <mach/xload.h>
#include <sizes.h>
#include <filetype.h>
void *omap_xload_boot_nand(int offset, int size)
static void *read_image_head(const char *name)
{
void *header = xmalloc(ARM_HEAD_SIZE);
struct cdev *cdev;
int ret;
cdev = cdev_open(name, O_RDONLY);
if (!cdev) {
printf("failed to open partition\n");
return NULL;
}
ret = cdev_read(cdev, header, ARM_HEAD_SIZE, 0, 0);
cdev_close(cdev);
if (ret != ARM_HEAD_SIZE) {
printf("failed to read from partition\n");
return NULL;
}
return header;
}
static unsigned int get_image_size(void *head)
{
unsigned int ret = 0;
unsigned int *psize = head + ARM_HEAD_SIZE_OFFSET;
if (is_barebox_arm_head(head))
ret = *psize;
debug("Detected barebox image size %u\n", ret);
return ret;
}
static void *omap_xload_boot_nand(int offset)
{
int ret;
void *to = xmalloc(size);
int size;
void *to, *header;
struct cdev *cdev;
devfs_add_partition("nand0", offset, size, DEVFS_PARTITION_FIXED, "x");
devfs_add_partition("nand0", offset, SZ_1M, DEVFS_PARTITION_FIXED, "x");
dev_add_bb_dev("x", "bbx");
header = read_image_head("bbx");
if (header == NULL)
return NULL;
size = get_image_size(header);
if (!size) {
printf("failed to get image size\n");
return NULL;
}
to = xmalloc(size);
cdev = cdev_open("bbx", O_RDONLY);
if (!cdev) {
printf("failed to open nand\n");
@ -32,7 +81,7 @@ void *omap_xload_boot_nand(int offset, int size)
return to;
}
void *omap_xload_boot_mmc(void)
static void *omap_xload_boot_mmc(void)
{
int ret;
void *buf;
@ -54,6 +103,42 @@ void *omap_xload_boot_mmc(void)
return buf;
}
static void *omap_xload_boot_spi(int offset)
{
int ret;
int size;
void *to, *header;
struct cdev *cdev;
devfs_add_partition("m25p0", offset, SZ_1M, DEVFS_PARTITION_FIXED, "x");
header = read_image_head("x");
if (header == NULL)
return NULL;
size = get_image_size(header);
if (!size) {
printf("failed to get image size\n");
return NULL;
}
to = xmalloc(size);
cdev = cdev_open("x", O_RDONLY);
if (!cdev) {
printf("failed to open spi flash\n");
return NULL;
}
ret = cdev_read(cdev, to, size, 0, 0);
if (ret != size) {
printf("failed to read from spi flash\n");
return NULL;
}
return to;
}
enum omap_boot_src omap_bootsrc(void)
{
#if defined(CONFIG_ARCH_OMAP3)
@ -80,7 +165,11 @@ int run_shell(void)
printf("unknown boot source. Fall back to nand\n");
case OMAP_BOOTSRC_NAND:
printf("booting from NAND\n");
func = omap_xload_boot_nand(SZ_128K, SZ_256K);
func = omap_xload_boot_nand(SZ_128K);
break;
case OMAP_BOOTSRC_SPI1:
printf("booting from SPI1\n");
func = omap_xload_boot_spi(SZ_128K);
break;
}

View File

@ -102,7 +102,7 @@ enum filetype file_detect_type(void *_buf)
if (strncmp(buf8, "#!/bin/sh", 9) == 0)
return filetype_sh;
if (buf[8] == 0x65726162 && buf[9] == 0x00786f62)
if (is_barebox_arm_head(_buf))
return filetype_arm_barebox;
if (buf[9] == 0x016f2818 || buf[9] == 0x18286f01)
return filetype_arm_zimage;

View File

@ -27,4 +27,20 @@ enum filetype file_detect_type(void *_buf);
enum filetype file_name_detect_type(const char *filename);
enum filetype is_fat_or_mbr(const unsigned char *sector, unsigned long *bootsec);
#define ARM_HEAD_SIZE 0x30
#define ARM_HEAD_MAGICWORD_OFFSET 0x20
#define ARM_HEAD_SIZE_OFFSET 0x2C
#ifdef CONFIG_ARM
static inline int is_barebox_arm_head(const char *head)
{
return !strcmp(head + ARM_HEAD_MAGICWORD_OFFSET, "barebox");
}
#else
static inline int is_barebox_arm_head(const char *head)
{
return 0;
}
#endif
#endif /* __FILE_TYPE_H */

1
scripts/.gitignore vendored
View File

@ -2,6 +2,7 @@ bareboxenv
bin2c
gen_netx_image
kallsyms
mk-am35xx-spi-image
mkimage
mkublheader
omap_signGP

View File

@ -9,7 +9,7 @@ hostprogs-y += bin2c
hostprogs-y += mkimage
hostprogs-y += bareboxenv
hostprogs-$(CONFIG_ARCH_NETX) += gen_netx_image
hostprogs-$(CONFIG_ARCH_OMAP) += omap_signGP
hostprogs-$(CONFIG_ARCH_OMAP) += omap_signGP mk-am35xx-spi-image
hostprogs-$(CONFIG_ARCH_S5PCxx) += s5p_cksum
hostprogs-$(CONFIG_ARCH_DAVINCI) += mkublheader

View File

@ -0,0 +1,141 @@
/*
* mk-am35xx-spi-image.c - convert a barebox image for SPI loading on AM35xx
*
* Copyright (C) 2012 Jan Luebbe <j.luebbe@pengutronix.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/**
* @file
* @brief convert a barebox image for SPI loading on AM35xx
*
* FileName: scripts/mk-am35xx-spi-image.c
*
* Booting from SPI on an AM35xx (and possibly other TI SOCs) requires
* a special format:
*
* - 32 bit image size in big-endian
* - 32 bit load address in big-endian
* - binary image converted from little- to big-endian
*
* This tool converts barebox.bin to the required format.
*/
#define _BSD_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <endian.h>
void usage(char *prgname)
{
printf("usage: %s [OPTION] FILE > IMAGE\n"
"\n"
"options:\n"
" -a <address> memory address for the loaded image in SRAM\n",
prgname);
}
int main(int argc, char *argv[])
{
FILE *input;
int opt;
off_t pos;
size_t size;
uint32_t addr = 0x40200000;
uint32_t temp;
while((opt = getopt(argc, argv, "a:")) != -1) {
switch (opt) {
case 'a':
addr = strtoul(optarg, NULL, 0);
break;
}
}
if (optind >= argc) {
usage(argv[0]);
exit(1);
}
input = fopen(argv[optind], "r");
if (input == NULL) {
perror("fopen");
exit(EXIT_FAILURE);
}
if (fseeko(input, 0, SEEK_END) == -1) {
perror("fseeko");
exit(EXIT_FAILURE);
}
pos = ftello(input);
if (pos == -1) {
perror("ftello");
exit(EXIT_FAILURE);
}
if (pos % 4) {
printf("error: image size must be a multiple of 4 bytes\n");
exit(EXIT_FAILURE);
}
if (pos > 0x100000) {
printf("error: image should be smaller than 1 MiB\n");
exit(EXIT_FAILURE);
}
if (fseeko(input, 0, SEEK_SET) == -1) {
perror("fseeko");
exit(EXIT_FAILURE);
}
/* image size */
temp = htobe32((uint32_t)pos);
fwrite(&temp, sizeof(uint32_t), 1, stdout);
/* memory address */
temp = htobe32(addr);
fwrite(&temp, sizeof(uint32_t), 1, stdout);
for (;;) {
size = fread(&temp, 1, sizeof(uint32_t), input);
if (!size)
break;
if (size != 4) {
perror("fread");
exit(EXIT_FAILURE);
}
temp = htobe32(le32toh(temp));
if (fwrite(&temp, 1, sizeof(uint32_t), stdout) != 4) {
perror("fwrite");
exit(EXIT_FAILURE);
}
}
if (fclose(input) != 0) {
perror("fclose");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}