summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Kconfig14
-rw-r--r--common/Makefile7
-rw-r--r--common/aboot.c244
-rw-r--r--common/board_f.c7
-rw-r--r--common/board_r.c24
-rw-r--r--common/cmd_ambapp.c559
-rw-r--r--common/cmd_gpt.c17
-rw-r--r--common/fb_mmc.c99
-rw-r--r--common/fb_nand.c213
-rw-r--r--common/image-sparse.c393
-rw-r--r--common/init/board_init.c3
11 files changed, 1167 insertions, 413 deletions
diff --git a/common/Kconfig b/common/Kconfig
index 0388a6c34d..440cb372a1 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -455,6 +455,20 @@ endmenu
menu "Misc commands"
+config CMD_AMBAPP
+ bool "ambapp"
+ depends on LEON3
+ default y
+ help
+ Lists AMBA Plug-n-Play information.
+
+config SYS_AMBAPP_PRINT_ON_STARTUP
+ bool "Show AMBA PnP info on startup"
+ depends on CMD_AMBAPP
+ default n
+ help
+ Show AMBA Plug-n-Play information on startup.
+
config CMD_TIME
bool "time"
help
diff --git a/common/Makefile b/common/Makefile
index d986cde7b9..d8dc892f72 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -276,10 +276,15 @@ obj-y += memsize.o
obj-y += stdio.o
# This option is not just y/n - it can have a numeric value
+ifdef CONFIG_FASTBOOT_FLASH
+obj-y += image-sparse.o
ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
-obj-y += aboot.o
obj-y += fb_mmc.o
endif
+ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
+obj-y += fb_nand.o
+endif
+endif
obj-$(CONFIG_CMD_BLOB) += cmd_blob.o
diff --git a/common/aboot.c b/common/aboot.c
deleted file mode 100644
index fba8e3e683..0000000000
--- a/common/aboot.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (c) 2009, Google Inc.
- * All rights reserved.
- *
- * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
- * Portions Copyright 2014 Broadcom Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of The Linux Foundation nor
- * the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
- *
- * NOTE:
- * Although it is very similar, this license text is not identical
- * to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT!
- */
-
-#include <config.h>
-#include <common.h>
-#include <aboot.h>
-#include <malloc.h>
-#include <part.h>
-#include <sparse_format.h>
-
-void write_sparse_image(block_dev_desc_t *dev_desc,
- disk_partition_t *info, const char *part_name,
- void *data, unsigned sz)
-{
- lbaint_t blk;
- lbaint_t blkcnt;
- lbaint_t blks;
- uint32_t bytes_written = 0;
- unsigned int chunk;
- unsigned int chunk_data_sz;
- uint32_t *fill_buf = NULL;
- uint32_t fill_val;
- sparse_header_t *sparse_header;
- chunk_header_t *chunk_header;
- uint32_t total_blocks = 0;
- int i;
-
- /* Read and skip over sparse image header */
- sparse_header = (sparse_header_t *) data;
-
- data += sparse_header->file_hdr_sz;
- if (sparse_header->file_hdr_sz > sizeof(sparse_header_t))
- {
- /*
- * Skip the remaining bytes in a header that is longer than
- * we expected.
- */
- data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
- }
-
- debug("=== Sparse Image Header ===\n");
- debug("magic: 0x%x\n", sparse_header->magic);
- debug("major_version: 0x%x\n", sparse_header->major_version);
- debug("minor_version: 0x%x\n", sparse_header->minor_version);
- debug("file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
- debug("chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
- debug("blk_sz: %d\n", sparse_header->blk_sz);
- debug("total_blks: %d\n", sparse_header->total_blks);
- debug("total_chunks: %d\n", sparse_header->total_chunks);
-
- /* verify sparse_header->blk_sz is an exact multiple of info->blksz */
- if (sparse_header->blk_sz !=
- (sparse_header->blk_sz & ~(info->blksz - 1))) {
- printf("%s: Sparse image block size issue [%u]\n",
- __func__, sparse_header->blk_sz);
- fastboot_fail("sparse image block size issue");
- return;
- }
-
- puts("Flashing Sparse Image\n");
-
- /* Start processing chunks */
- blk = info->start;
- for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
- {
- /* Read and skip over chunk header */
- chunk_header = (chunk_header_t *) data;
- data += sizeof(chunk_header_t);
-
- if (chunk_header->chunk_type != CHUNK_TYPE_RAW) {
- debug("=== Chunk Header ===\n");
- debug("chunk_type: 0x%x\n", chunk_header->chunk_type);
- debug("chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
- debug("total_size: 0x%x\n", chunk_header->total_sz);
- }
-
- if (sparse_header->chunk_hdr_sz > sizeof(chunk_header_t))
- {
- /*
- * Skip the remaining bytes in a header that is longer
- * than we expected.
- */
- data += (sparse_header->chunk_hdr_sz -
- sizeof(chunk_header_t));
- }
-
- chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
- blkcnt = chunk_data_sz / info->blksz;
- switch (chunk_header->chunk_type)
- {
- case CHUNK_TYPE_RAW:
- if (chunk_header->total_sz !=
- (sparse_header->chunk_hdr_sz + chunk_data_sz))
- {
- fastboot_fail(
- "Bogus chunk size for chunk type Raw");
- return;
- }
-
- if (blk + blkcnt > info->start + info->size) {
- printf(
- "%s: Request would exceed partition size!\n",
- __func__);
- fastboot_fail(
- "Request would exceed partition size!");
- return;
- }
-
- blks = dev_desc->block_write(dev_desc->dev, blk, blkcnt,
- data);
- if (blks != blkcnt) {
- printf("%s: Write failed " LBAFU "\n",
- __func__, blks);
- fastboot_fail("flash write failure");
- return;
- }
- blk += blkcnt;
- bytes_written += blkcnt * info->blksz;
- total_blocks += chunk_header->chunk_sz;
- data += chunk_data_sz;
- break;
-
- case CHUNK_TYPE_FILL:
- if (chunk_header->total_sz !=
- (sparse_header->chunk_hdr_sz + sizeof(uint32_t)))
- {
- fastboot_fail(
- "Bogus chunk size for chunk type FILL");
- return;
- }
-
- fill_buf = (uint32_t *)
- memalign(ARCH_DMA_MINALIGN,
- ROUNDUP(info->blksz,
- ARCH_DMA_MINALIGN));
- if (!fill_buf)
- {
- fastboot_fail(
- "Malloc failed for: CHUNK_TYPE_FILL");
- return;
- }
-
- fill_val = *(uint32_t *)data;
- data = (char *) data + sizeof(uint32_t);
-
- for (i = 0; i < (info->blksz / sizeof(fill_val)); i++)
- fill_buf[i] = fill_val;
-
- if (blk + blkcnt > info->start + info->size) {
- printf(
- "%s: Request would exceed partition size!\n",
- __func__);
- fastboot_fail(
- "Request would exceed partition size!");
- return;
- }
-
- for (i = 0; i < blkcnt; i++) {
- blks = dev_desc->block_write(dev_desc->dev,
- blk, 1, fill_buf);
- if (blks != 1) {
- printf(
- "%s: Write failed, block # " LBAFU "\n",
- __func__, blkcnt);
- fastboot_fail("flash write failure");
- free(fill_buf);
- return;
- }
- blk++;
- }
- bytes_written += blkcnt * info->blksz;
- total_blocks += chunk_data_sz / sparse_header->blk_sz;
-
- free(fill_buf);
- break;
-
- case CHUNK_TYPE_DONT_CARE:
- blk += blkcnt;
- total_blocks += chunk_header->chunk_sz;
- break;
-
- case CHUNK_TYPE_CRC32:
- if (chunk_header->total_sz !=
- sparse_header->chunk_hdr_sz)
- {
- fastboot_fail(
- "Bogus chunk size for chunk type Dont Care");
- return;
- }
- total_blocks += chunk_header->chunk_sz;
- data += chunk_data_sz;
- break;
-
- default:
- printf("%s: Unknown chunk type: %x\n", __func__,
- chunk_header->chunk_type);
- fastboot_fail("Unknown chunk type");
- return;
- }
- }
-
- debug("Wrote %d blocks, expected to write %d blocks\n",
- total_blocks, sparse_header->total_blks);
- printf("........ wrote %u bytes to '%s'\n", bytes_written, part_name);
-
- if (total_blocks != sparse_header->total_blks)
- fastboot_fail("sparse image write failure");
-
- fastboot_okay("");
- return;
-}
diff --git a/common/board_f.c b/common/board_f.c
index 725eb18427..04c273e2fe 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -796,7 +796,7 @@ static init_fnc_t init_sequence_f[] = {
/* TODO: can we rename this to timer_init()? */
init_timebase,
#endif
-#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
+#if defined(CONFIG_X86) || defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32)
timer_init, /* initialize timer */
#endif
@@ -808,10 +808,7 @@ static init_fnc_t init_sequence_f[] = {
#if defined(CONFIG_BOARD_POSTCLK_INIT)
board_postclk_init,
#endif
-#ifdef CONFIG_SYS_FSL_CLK
- get_clocks,
-#endif
-#ifdef CONFIG_M68K
+#if defined(CONFIG_SYS_FSL_CLK) || defined(CONFIG_M68K)
get_clocks,
#endif
env_init, /* initialize environment */
diff --git a/common/board_r.c b/common/board_r.c
index c4fd3eaf8c..c6aa7e5224 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -46,6 +46,9 @@
#include <stdio_dev.h>
#include <trace.h>
#include <watchdog.h>
+#ifdef CONFIG_CMD_AMBAPP
+#include <ambapp.h>
+#endif
#ifdef CONFIG_ADDR_MAP
#include <asm/mmu.h>
#endif
@@ -559,6 +562,18 @@ static int initr_status_led(void)
}
#endif
+#if defined(CONFIG_CMD_AMBAPP) && defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP)
+extern int do_ambapp_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+
+static int initr_ambapp_print(void)
+{
+ puts("AMBA:\n");
+ do_ambapp_print(NULL, 0, 0, NULL);
+
+ return 0;
+}
+#endif
+
#if defined(CONFIG_CMD_SCSI)
static int initr_scsi(void)
{
@@ -837,8 +852,7 @@ init_fnc_t init_sequence_r[] = {
#if defined(CONFIG_ARM) || defined(CONFIG_AVR32)
initr_enable_interrupts,
#endif
-#if defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) \
- || defined(CONFIG_M68K)
+#if defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) || defined(CONFIG_M68K)
timer_init, /* initialize timer */
#endif
#if defined(CONFIG_STATUS_LED)
@@ -851,6 +865,12 @@ init_fnc_t init_sequence_r[] = {
#ifdef CONFIG_BOARD_LATE_INIT
board_late_init,
#endif
+#if defined(CONFIG_CMD_AMBAPP)
+ ambapp_init_reloc,
+#if defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP)
+ initr_ambapp_print,
+#endif
+#endif
#ifdef CONFIG_CMD_SCSI
INIT_FUNC_WATCHDOG_RESET
initr_scsi,
diff --git a/common/cmd_ambapp.c b/common/cmd_ambapp.c
index 2a1995a761..4b6d1741e9 100644
--- a/common/cmd_ambapp.c
+++ b/common/cmd_ambapp.c
@@ -15,92 +15,375 @@
DECLARE_GLOBAL_DATA_PTR;
-/* We put these variables into .data section so that they are zero
- * when entering the AMBA Plug & Play routines (in cpu/cpu/ambapp.c)
- * the first time. BSS is not garantueed to be zero since BSS
- * hasn't been cleared the first times entering the CPU AMBA functions.
- *
- * The AMBA PnP routines call these functions if ambapp_???_print is set.
- *
- */
-int ambapp_apb_print __attribute__ ((section(".data"))) = 0;
-int ambapp_ahb_print __attribute__ ((section(".data"))) = 0;
-
typedef struct {
int device_id;
char *name;
+ char *desc;
} ambapp_device_name;
-static ambapp_device_name gaisler_devices[] = {
- {GAISLER_LEON3, "GAISLER_LEON3"},
- {GAISLER_LEON3DSU, "GAISLER_LEON3DSU"},
- {GAISLER_ETHAHB, "GAISLER_ETHAHB"},
- {GAISLER_ETHMAC, "GAISLER_ETHMAC"},
- {GAISLER_APBMST, "GAISLER_APBMST"},
- {GAISLER_AHBUART, "GAISLER_AHBUART"},
- {GAISLER_SRCTRL, "GAISLER_SRCTRL"},
- {GAISLER_SDCTRL, "GAISLER_SDCTRL"},
- {GAISLER_APBUART, "GAISLER_APBUART"},
- {GAISLER_IRQMP, "GAISLER_IRQMP"},
- {GAISLER_AHBRAM, "GAISLER_AHBRAM"},
- {GAISLER_GPTIMER, "GAISLER_GPTIMER"},
- {GAISLER_PCITRG, "GAISLER_PCITRG"},
- {GAISLER_PCISBRG, "GAISLER_PCISBRG"},
- {GAISLER_PCIFBRG, "GAISLER_PCIFBRG"},
- {GAISLER_PCITRACE, "GAISLER_PCITRACE"},
- {GAISLER_AHBTRACE, "GAISLER_AHBTRACE"},
- {GAISLER_ETHDSU, "GAISLER_ETHDSU"},
- {GAISLER_PIOPORT, "GAISLER_PIOPORT"},
- {GAISLER_AHBJTAG, "GAISLER_AHBJTAG"},
- {GAISLER_ATACTRL, "GAISLER_ATACTRL"},
- {GAISLER_VGA, "GAISLER_VGA"},
- {GAISLER_KBD, "GAISLER_KBD"},
- {GAISLER_L2TIME, "GAISLER_L2TIME"},
- {GAISLER_L2C, "GAISLER_L2C"},
- {GAISLER_PLUGPLAY, "GAISLER_PLUGPLAY"},
- {GAISLER_SPW, "GAISLER_SPW"},
- {GAISLER_SPW2, "GAISLER_SPW2"},
- {GAISLER_EHCI, "GAISLER_EHCI"},
- {GAISLER_UHCI, "GAISLER_UHCI"},
- {GAISLER_AHBSTAT, "GAISLER_AHBSTAT"},
- {GAISLER_DDR2SPA, "GAISLER_DDR2SPA"},
- {GAISLER_DDRSPA, "GAISLER_DDRSPA"},
- {0, NULL}
+typedef struct {
+ unsigned int vendor_id;
+ char *name;
+ char *desc;
+ ambapp_device_name *devices;
+} ambapp_vendor_devnames;
+
+/** Vendor GAISLER devices */
+static ambapp_device_name GAISLER_devices[] = {
+ {GAISLER_LEON2DSU, "LEON2DSU", "Leon2 Debug Support Unit"},
+ {GAISLER_LEON3, "LEON3", "Leon3 SPARC V8 Processor"},
+ {GAISLER_LEON3DSU, "LEON3DSU", "Leon3 Debug Support Unit"},
+ {GAISLER_ETHAHB, "ETHAHB", "OC ethernet AHB interface"},
+ {GAISLER_APBMST, "APBMST", "AHB/APB Bridge"},
+ {GAISLER_AHBUART, "AHBUART", "AHB Debug UART"},
+ {GAISLER_SRCTRL, "SRCTRL", "Simple SRAM Controller"},
+ {GAISLER_SDCTRL, "SDCTRL", "PC133 SDRAM Controller"},
+ {GAISLER_SSRCTRL, "SSRCTRL", "Synchronous SRAM Controller"},
+ {GAISLER_APBUART, "APBUART", "Generic UART"},
+ {GAISLER_IRQMP, "IRQMP", "Multi-processor Interrupt Ctrl."},
+ {GAISLER_AHBRAM, "AHBRAM", "Single-port AHB SRAM module"},
+ {GAISLER_AHBDPRAM, "AHBDPRAM", "Dual-port AHB SRAM module"},
+ {GAISLER_GPTIMER, "GPTIMER", "Modular Timer Unit"},
+ {GAISLER_PCITRG, "PCITRG", "Simple 32-bit PCI Target"},
+ {GAISLER_PCISBRG, "PCISBRG", "Simple 32-bit PCI Bridge"},
+ {GAISLER_PCIFBRG, "PCIFBRG", "Fast 32-bit PCI Bridge"},
+ {GAISLER_PCITRACE, "PCITRACE", "32-bit PCI Trace Buffer"},
+ {GAISLER_DMACTRL, "DMACTRL", "AMBA DMA controller"},
+ {GAISLER_AHBTRACE, "AHBTRACE", "AMBA Trace Buffer"},
+ {GAISLER_DSUCTRL, "DSUCTRL", "DSU/ETH controller"},
+ {GAISLER_CANAHB, "CANAHB", "OC CAN AHB interface"},
+ {GAISLER_GPIO, "GPIO", "General Purpose I/O port"},
+ {GAISLER_AHBROM, "AHBROM", "Generic AHB ROM"},
+ {GAISLER_AHBJTAG, "AHBJTAG", "JTAG Debug Link"},
+ {GAISLER_ETHMAC, "ETHMAC", "GR Ethernet MAC"},
+ {GAISLER_SWNODE, "SWNODE", "SpaceWire Node Interface"},
+ {GAISLER_SPW, "SPW", "SpaceWire Serial Link"},
+ {GAISLER_AHB2AHB, "AHB2AHB", "AHB-to-AHB Bridge"},
+ {GAISLER_USBDC, "USBDC", "GR USB 2.0 Device Controller"},
+ {GAISLER_USB_DCL, "USB_DCL", "USB Debug Communication Link"},
+ {GAISLER_DDRMP, "DDRMP", "Multi-port DDR controller"},
+ {GAISLER_ATACTRL, "ATACTRL", "ATA controller"},
+ {GAISLER_DDRSP, "DDRSP", "Single-port DDR266 controller"},
+ {GAISLER_EHCI, "EHCI", "USB Enhanced Host Controller"},
+ {GAISLER_UHCI, "UHCI", "USB Universal Host Controller"},
+ {GAISLER_I2CMST, "I2CMST", "AMBA Wrapper for OC I2C-master"},
+ {GAISLER_SPW2, "SPW2", "GRSPW2 SpaceWire Serial Link"},
+ {GAISLER_AHBDMA, "AHBDMA", ""},
+ {GAISLER_NUHOSP3, "NUHOSP3", "Nuhorizons Spartan3 IO I/F"},
+ {GAISLER_CLKGATE, "CLKGATE", "Clock gating unit"},
+ {GAISLER_SPICTRL, "SPICTRL", "SPI Controller"},
+ {GAISLER_DDR2SP, "DDR2SP", "Single-port DDR2 controller"},
+ {GAISLER_SLINK, "SLINK", "SLINK Master"},
+ {GAISLER_GRTM, "GRTM", "CCSDS Telemetry Encoder"},
+ {GAISLER_GRTC, "GRTC", "CCSDS Telecommand Decoder"},
+ {GAISLER_GRPW, "GRPW", "PacketWire to AMBA AHB I/F"},
+ {GAISLER_GRCTM, "GRCTM", "CCSDS Time Manager"},
+ {GAISLER_GRHCAN, "GRHCAN", "ESA HurriCANe CAN with DMA"},
+ {GAISLER_GRFIFO, "GRFIFO", "FIFO Controller"},
+ {GAISLER_GRADCDAC, "GRADCDAC", "ADC / DAC Interface"},
+ {GAISLER_GRPULSE, "GRPULSE", "General Purpose I/O with Pulses"},
+ {GAISLER_GRTIMER, "GRTIMER", "Timer Unit with Latches"},
+ {GAISLER_AHB2PP, "AHB2PP", "AMBA AHB to Packet Parallel I/F"},
+ {GAISLER_GRVERSION, "GRVERSION", "Version and Revision Register"},
+ {GAISLER_APB2PW, "APB2PW", "PacketWire Transmit Interface"},
+ {GAISLER_PW2APB, "PW2APB", "PacketWire Receive Interface"},
+ {GAISLER_GRCAN, "GRCAN", "CAN Controller with DMA"},
+ {GAISLER_I2CSLV, "I2CSLV", "I2C Slave"},
+ {GAISLER_U16550, "U16550", "Simple 16550 UART"},
+ {GAISLER_AHBMST_EM, "AHBMST_EM", "AMBA Master Emulator"},
+ {GAISLER_AHBSLV_EM, "AHBSLV_EM", "AMBA Slave Emulator"},
+ {GAISLER_GRTESTMOD, "GRTESTMOD", "Test report module"},
+ {GAISLER_ASCS, "ASCS", "ASCS Master"},
+ {GAISLER_IPMVBCTRL, "IPMVBCTRL", "IPM-bus/MVBC memory controller"},
+ {GAISLER_SPIMCTRL, "SPIMCTRL", "SPI Memory Controller"},
+ {GAISLER_L4STAT, "L4STAT", "Leon4 Statistics Module"},
+ {GAISLER_LEON4, "LEON4", "Leon4 SPARC V8 Processor"},
+ {GAISLER_LEON4DSU, "LEON4DSU", "Leon4 Debug Support Unit"},
+ {GAISLER_PWM, "PWM", "PWM generator"},
+ {GAISLER_L2CACHE, "L2CACHE", "L2-Cache Controller"},
+ {GAISLER_SDCTRL64, "SDCTRL64", "64-bit PC133 SDRAM Controller"},
+ {GAISLER_GR1553B, "GR1553B", "MIL-STD-1553B Interface"},
+ {GAISLER_1553TST, "1553TST", "MIL-STD-1553B Test Device"},
+ {GAISLER_GRIOMMU, "GRIOMMU", "I/O Memory Management Unit"},
+ {GAISLER_FTAHBRAM, "FTAHBRAM", "Generic FT AHB SRAM module"},
+ {GAISLER_FTSRCTRL, "FTSRCTRL", "Simple FT SRAM Controller"},
+ {GAISLER_AHBSTAT, "AHBSTAT", "AHB Status Register"},
+ {GAISLER_LEON3FT, "LEON3FT", "Leon3-FT SPARC V8 Processor"},
+ {GAISLER_FTMCTRL, "FTMCTRL", "Memory controller with EDAC"},
+ {GAISLER_FTSDCTRL, "FTSDCTRL", "FT PC133 SDRAM Controller"},
+ {GAISLER_FTSRCTRL8, "FTSRCTRL8", "FT 8-bit SRAM/16-bit IO Ctrl"},
+ {GAISLER_MEMSCRUB, "MEMSCRUB", "AHB Memory Scrubber"},
+ {GAISLER_FTSDCTRL64, "FTSDCTRL64", "64-bit FT SDRAM Controller"},
+ {GAISLER_APBPS2, "APBPS2", "PS2 interface"},
+ {GAISLER_VGACTRL, "VGACTRL", "VGA controller"},
+ {GAISLER_LOGAN, "LOGAN", "On chip Logic Analyzer"},
+ {GAISLER_SVGACTRL, "SVGACTRL", "SVGA frame buffer"},
+ {GAISLER_T1AHB, "T1AHB", "Niagara T1 PCX/AHB bridge"},
+ {GAISLER_MP7WRAP, "MP7WRAP", "CoreMP7 wrapper"},
+ {GAISLER_GRSYSMON, "GRSYSMON", "AMBA wrapper for System Monitor"},
+ {GAISLER_GRACECTRL, "GRACECTRL", "System ACE I/F Controller"},
+ {GAISLER_ATAHBSLV, "ATAHBSLV", "AMBA Test Framework AHB Slave"},
+ {GAISLER_ATAHBMST, "ATAHBMST", "AMBA Test Framework AHB Master"},
+ {GAISLER_ATAPBSLV, "ATAPBSLV", "AMBA Test Framework APB Slave"},
+ {GAISLER_B1553BC, "B1553BC", "AMBA Wrapper for Core1553BBC"},
+ {GAISLER_B1553RT, "B1553RT", "AMBA Wrapper for Core1553BRT"},
+ {GAISLER_B1553BRM, "B1553BRM", "AMBA Wrapper for Core1553BRM"},
+ {GAISLER_AES, "AES", "Advanced Encryption Standard"},
+ {GAISLER_ECC, "ECC", "Elliptic Curve Cryptography"},
+ {GAISLER_PCIF, "PCIF", "AMBA Wrapper for CorePCIF"},
+ {GAISLER_CLKMOD, "CLKMOD", "CPU Clock Switching Ctrl module"},
+ {GAISLER_HAPSTRAK, "HAPSTRAK", "HAPS HapsTrak I/O Port"},
+ {GAISLER_TEST_1X2, "TEST_1X2", "HAPS TEST_1x2 interface"},
+ {GAISLER_WILD2AHB, "WILD2AHB", "WildCard CardBus interface"},
+ {GAISLER_BIO1, "BIO1", "Basic I/O board BIO1"},
+ {GAISLER_AESDMA, "AESDMA", "AES 256 DMA"},
+ {GAISLER_SATCAN, "SATCAN", "SatCAN controller"},
+ {GAISLER_CANMUX, "CANMUX", "CAN Bus multiplexer"},
+ {GAISLER_GRTMRX, "GRTMRX", "CCSDS Telemetry Receiver"},
+ {GAISLER_GRTCTX, "GRTCTX", "CCSDS Telecommand Transmitter"},
+ {GAISLER_GRTMDESC, "GRTMDESC", "CCSDS Telemetry Descriptor"},
+ {GAISLER_GRTMVC, "GRTMVC", "CCSDS Telemetry VC Generator"},
+ {GAISLER_GEFFE, "GEFFE", "Geffe Generator"},
+ {GAISLER_GPREG, "GPREG", "General Purpose Register"},
+ {GAISLER_GRTMPAHB, "GRTMPAHB", "CCSDS Telemetry VC AHB Input"},
+ {GAISLER_SPWCUC, "SPWCUC", "CCSDS CUC / SpaceWire I/F"},
+ {GAISLER_SPW2_DMA, "SPW2_DMA", "GRSPW Router DMA interface"},
+ {GAISLER_SPWROUTER, "SPWROUTER", "GRSPW Router"},
+ {0, NULL, NULL}
};
-static ambapp_device_name esa_devices[] = {
- {ESA_LEON2, "ESA_LEON2"},
- {ESA_MCTRL, "ESA_MCTRL"},
- {0, NULL}
+
+/** Vendor PENDER devices */
+static ambapp_device_name PENDER_devices[] = {
+ {0, NULL, NULL}
};
-static ambapp_device_name opencores_devices[] = {
- {OPENCORES_PCIBR, "OPENCORES_PCIBR"},
- {OPENCORES_ETHMAC, "OPENCORES_ETHMAC"},
+
+/** Vendor ESA devices */
+static ambapp_device_name ESA_devices[] = {
+ {ESA_LEON2, "LEON2", "Leon2 SPARC V8 Processor"},
+ {ESA_LEON2APB, "LEON2APB", "Leon2 Peripheral Bus"},
+ {ESA_IRQ, "IRQ", "Leon2 Interrupt Controller"},
+ {ESA_TIMER, "TIMER", "Leon2 Timer"},
+ {ESA_UART, "UART", "Leon2 UART"},
+ {ESA_CFG, "CFG", "Leon2 Configuration Register"},
+ {ESA_IO, "IO", "Leon2 Input/Output"},
+ {ESA_MCTRL, "MCTRL", "Leon2 Memory Controller"},
+ {ESA_PCIARB, "PCIARB", "PCI Arbiter"},
+ {ESA_HURRICANE, "HURRICANE", "HurriCANe/HurryAMBA CAN Ctrl"},
+ {ESA_SPW_RMAP, "SPW_RMAP", "UoD/Saab SpaceWire/RMAP link"},
+ {ESA_AHBUART, "AHBUART", "Leon2 AHB Debug UART"},
+ {ESA_SPWA, "SPWA", "ESA/ASTRIUM SpaceWire link"},
+ {ESA_BOSCHCAN, "BOSCHCAN", "SSC/BOSCH CAN Ctrl"},
+ {ESA_IRQ2, "IRQ2", "Leon2 Secondary Irq Controller"},
+ {ESA_AHBSTAT, "AHBSTAT", "Leon2 AHB Status Register"},
+ {ESA_WPROT, "WPROT", "Leon2 Write Protection"},
+ {ESA_WPROT2, "WPROT2", "Leon2 Extended Write Protection"},
+ {ESA_PDEC3AMBA, "PDEC3AMBA", "ESA CCSDS PDEC3AMBA TC Decoder"},
+ {ESA_PTME3AMBA, "PTME3AMBA", "ESA CCSDS PTME3AMBA TM Encoder"},
+ {0, NULL, NULL}
+};
+
+
+/** Vendor ASTRIUM devices */
+static ambapp_device_name ASTRIUM_devices[] = {
+ {0, NULL, NULL}
+};
+
+
+/** Vendor OPENCHIP devices */
+static ambapp_device_name OPENCHIP_devices[] = {
+ {OPENCHIP_APBGPIO, "APBGPIO", "APB General Purpose IO"},
+ {OPENCHIP_APBI2C, "APBI2C", "APB I2C Interface"},
+ {OPENCHIP_APBSPI, "APBSPI", "APB SPI Interface"},
+ {OPENCHIP_APBCHARLCD, "APBCHARLCD", "APB Character LCD"},
+ {OPENCHIP_APBPWM, "APBPWM", "APB PWM"},
+ {OPENCHIP_APBPS2, "APBPS2", "APB PS/2 Interface"},
+ {OPENCHIP_APBMMCSD, "APBMMCSD", "APB MMC/SD Card Interface"},
+ {OPENCHIP_APBNAND, "APBNAND", "APB NAND(SmartMedia) Interface"},
+ {OPENCHIP_APBLPC, "APBLPC", "APB LPC Interface"},
+ {OPENCHIP_APBCF, "APBCF", "APB CompactFlash (IDE)"},
+ {OPENCHIP_APBSYSACE, "APBSYSACE", "APB SystemACE Interface"},
+ {OPENCHIP_APB1WIRE, "APB1WIRE", "APB 1-Wire Interface"},
+ {OPENCHIP_APBJTAG, "APBJTAG", "APB JTAG TAP Master"},
+ {OPENCHIP_APBSUI, "APBSUI", "APB Simple User Interface"},
+ {0, NULL, NULL}
+};
+
+
+/** Vendor OPENCORES devices */
+static ambapp_device_name OPENCORES_devices[] = {
+ {OPENCORES_PCIBR, "PCIBR", "PCI Bridge"},
+ {OPENCORES_ETHMAC, "ETHMAC", "Ethernet MAC"},
{0, NULL}
};
-typedef struct {
- unsigned int vendor_id;
- char *name;
- ambapp_device_name *devices;
-} ambapp_vendor_devnames;
+/** Vendor CONTRIB devices */
+static ambapp_device_name CONTRIB_devices[] = {
+ {CONTRIB_CORE1, "CORE1", "Contributed core 1"},
+ {CONTRIB_CORE2, "CORE2", "Contributed core 2"},
+ {0, NULL, NULL}
+};
+
+
+/** Vendor EONIC devices */
+static ambapp_device_name EONIC_devices[] = {
+ {0, NULL, NULL}
+};
+
+
+/** Vendor RADIONOR devices */
+static ambapp_device_name RADIONOR_devices[] = {
+ {0, NULL, NULL}
+};
+
+
+/** Vendor GLEICHMANN devices */
+static ambapp_device_name GLEICHMANN_devices[] = {
+ {GLEICHMANN_CUSTOM, "CUSTOM", "Custom device"},
+ {GLEICHMANN_GEOLCD01, "GEOLCD01", "GEOLCD01 graphics system"},
+ {GLEICHMANN_DAC, "DAC", "Sigma delta DAC"},
+ {GLEICHMANN_HPI, "HPI", "AHB-to-HPI bridge"},
+ {GLEICHMANN_SPI, "SPI", "SPI master"},
+ {GLEICHMANN_HIFC, "HIFC", "Human interface controller"},
+ {GLEICHMANN_ADCDAC, "ADCDAC", "Sigma delta ADC/DAC"},
+ {GLEICHMANN_SPIOC, "SPIOC", ""},
+ {GLEICHMANN_AC97, "AC97", ""},
+ {0, NULL, NULL}
+};
+
+
+/** Vendor MENTA devices */
+static ambapp_device_name MENTA_devices[] = {
+ {0, NULL, NULL}
+};
+
+
+/** Vendor SUN devices */
+static ambapp_device_name SUN_devices[] = {
+ {SUN_T1, "T1", "Niagara T1 SPARC V9 Processor"},
+ {SUN_S1, "S1", "Niagara S1 SPARC V9 Processor"},
+ {0, NULL, NULL}
+};
+
+
+/** Vendor MOVIDIA devices */
+static ambapp_device_name MOVIDIA_devices[] = {
+ {0, NULL, NULL}
+};
+
+
+/** Vendor ORBITA devices */
+static ambapp_device_name ORBITA_devices[] = {
+ {ORBITA_1553B, "1553B", "MIL-STD-1553B Controller"},
+ {ORBITA_429, "429", "429 Interface"},
+ {ORBITA_SPI, "SPI", "SPI Interface"},
+ {ORBITA_I2C, "I2C", "I2C Interface"},
+ {ORBITA_SMARTCARD, "SMARTCARD", "Smart Card Reader"},
+ {ORBITA_SDCARD, "SDCARD", "SD Card Reader"},
+ {ORBITA_UART16550, "UART16550", "16550 UART"},
+ {ORBITA_CRYPTO, "CRYPTO", "Crypto Engine"},
+ {ORBITA_SYSIF, "SYSIF", "System Interface"},
+ {ORBITA_PIO, "PIO", "Programmable IO module"},
+ {ORBITA_RTC, "RTC", "Real-Time Clock"},
+ {ORBITA_COLORLCD, "COLORLCD", "Color LCD Controller"},
+ {ORBITA_PCI, "PCI", "PCI Module"},
+ {ORBITA_DSP, "DSP", "DPS Co-Processor"},
+ {ORBITA_USBHOST, "USBHOST", "USB Host"},
+ {ORBITA_USBDEV, "USBDEV", "USB Device"},
+ {0, NULL, NULL}
+};
+
+
+/** Vendor SYNOPSYS devices */
+static ambapp_device_name SYNOPSYS_devices[] = {
+ {0, NULL, NULL}
+};
+
+
+/** Vendor NASA devices */
+static ambapp_device_name NASA_devices[] = {
+ {NASA_EP32, "EP32", "EP32 Forth processor"},
+ {0, NULL, NULL}
+};
+
+
+/** Vendor CAL devices */
+static ambapp_device_name CAL_devices[] = {
+ {CAL_DDRCTRL, "DDRCTRL", ""},
+ {0, NULL, NULL}
+};
+
+
+/** Vendor EMBEDDIT devices */
+static ambapp_device_name EMBEDDIT_devices[] = {
+ {0, NULL, NULL}
+};
+
+
+/** Vendor CETON devices */
+static ambapp_device_name CETON_devices[] = {
+ {0, NULL, NULL}
+};
+
+
+/** Vendor S3 devices */
+static ambapp_device_name S3_devices[] = {
+ {0, NULL, NULL}
+};
+
+
+/** Vendor ACTEL devices */
+static ambapp_device_name ACTEL_devices[] = {
+ {ACTEL_COREMP7, "COREMP7", "CoreMP7 Processor"},
+ {0, NULL, NULL}
+};
+
+
+/** Vendor APPLECORE devices */
+static ambapp_device_name APPLECORE_devices[] = {
+ {APPLECORE_UTLEON3, "UTLEON3", "AppleCore uT-LEON3 Processor"},
+ {APPLECORE_UTLEON3DSU, "UTLEON3DSU", "AppleCore uT-LEON3 DSU"},
+ {0, NULL, NULL}
+};
+
+
+/** Vendors and their devices */
static ambapp_vendor_devnames vendors[] = {
- {VENDOR_GAISLER, "VENDOR_GAISLER", gaisler_devices},
- {VENDOR_ESA, "VENDOR_ESA", esa_devices},
- {VENDOR_OPENCORES, "VENDOR_OPENCORES", opencores_devices},
- {0, NULL, 0}
+ {VENDOR_GAISLER, "GAISLER", "Gaisler Research", GAISLER_devices},
+ {VENDOR_PENDER, "PENDER", "", PENDER_devices},
+ {VENDOR_ESA, "ESA", "European Space Agency", ESA_devices},
+ {VENDOR_ASTRIUM, "ASTRIUM", "", ASTRIUM_devices},
+ {VENDOR_OPENCHIP, "OPENCHIP", "OpenChip", OPENCHIP_devices},
+ {VENDOR_OPENCORES, "OPENCORES", "OpenCores", OPENCORES_devices},
+ {VENDOR_CONTRIB, "CONTRIB", "Various contributions", CONTRIB_devices},
+ {VENDOR_EONIC, "EONIC", "Eonic BV", EONIC_devices},
+ {VENDOR_RADIONOR, "RADIONOR", "Radionor Communications", RADIONOR_devices},
+ {VENDOR_GLEICHMANN, "GLEICHMANN", "Gleichmann Electronics", GLEICHMANN_devices},
+ {VENDOR_MENTA, "MENTA", "Menta", MENTA_devices},
+ {VENDOR_SUN, "SUN", "Sun Microsystems", SUN_devices},
+ {VENDOR_MOVIDIA, "MOVIDIA", "", MOVIDIA_devices},
+ {VENDOR_ORBITA, "ORBITA", "Orbita", ORBITA_devices},
+ {VENDOR_SYNOPSYS, "SYNOPSYS", "Synopsys Inc.", SYNOPSYS_devices},
+ {VENDOR_NASA, "NASA", "NASA", NASA_devices},
+ {VENDOR_S3, "S3", "S3 Group", S3_devices},
+ {VENDOR_CAL, "CAL", "", CAL_devices},
+ {VENDOR_EMBEDDIT, "EMBEDDIT", "Embedd.it", EMBEDDIT_devices},
+ {VENDOR_CETON, "CETON", "Ceton Corporation", CETON_devices},
+ {VENDOR_ACTEL, "ACTEL", "Actel Corporation", ACTEL_devices},
+ {VENDOR_APPLECORE, "APPLECORE", "AppleCore", APPLECORE_devices},
+ {0, NULL, NULL, NULL}
};
-static char *ambapp_get_devname(ambapp_device_name * devs, int id)
+static ambapp_device_name *ambapp_get_dev(ambapp_device_name *devs, int id)
{
if (!devs)
return NULL;
while (devs->device_id > 0) {
if (devs->device_id == id)
- return devs->name;
+ return devs;
devs++;
}
return NULL;
@@ -109,10 +392,31 @@ static char *ambapp_get_devname(ambapp_device_name * devs, int id)
char *ambapp_device_id2str(int vendor, int id)
{
ambapp_vendor_devnames *ven = &vendors[0];
+ ambapp_device_name *dev;
+
+ while (ven->vendor_id > 0) {
+ if (ven->vendor_id == vendor) {
+ dev = ambapp_get_dev(ven->devices, id);
+ if (!dev)
+ return NULL;
+ return dev->name;
+ }
+ ven++;
+ }
+ return NULL;
+}
+
+char *ambapp_device_id2desc(int vendor, int id)
+{
+ ambapp_vendor_devnames *ven = &vendors[0];
+ ambapp_device_name *dev;
while (ven->vendor_id > 0) {
if (ven->vendor_id == vendor) {
- return ambapp_get_devname(ven->devices, id);
+ dev = ambapp_get_dev(ven->devices, id);
+ if (!dev)
+ return NULL;
+ return dev->desc;
}
ven++;
}
@@ -134,101 +438,106 @@ char *ambapp_vendor_id2str(int vendor)
static char *unknown = "unknown";
+char *ambapp_type_names[4] = {
+ /* 0 */ "UNUSED",
+ /* 1 */ "apb",
+ /* 2 */ "ahbmem",
+ /* 3 */ "ahbio"
+};
+
/* Print one APB device */
-void ambapp_print_apb(apbctrl_pp_dev * apb, ambapp_ahbdev * apbmst, int index)
+void ambapp_print_apb(ambapp_apbdev *dev, int index)
{
char *dev_str, *ven_str;
- int irq, ver, vendor, deviceid;
- unsigned int address, apbmst_base, mask;
-
- vendor = amba_vendor(apb->conf);
- deviceid = amba_device(apb->conf);
- irq = amba_irq(apb->conf);
- ver = amba_ver(apb->conf);
- apbmst_base = apbmst->address[0] & LEON3_IO_AREA;
- address = (apbmst_base | (((apb->bar & 0xfff00000) >> 12))) &
- (((apb->bar & 0x0000fff0) << 4) | 0xfff00000);
+ unsigned int freq;
- mask = amba_membar_mask(apb->bar) << 8;
- mask = ((~mask) & 0x000fffff) + 1;
-
- ven_str = ambapp_vendor_id2str(vendor);
+ ven_str = ambapp_vendor_id2str(dev->vendor);
if (!ven_str) {
ven_str = unknown;
dev_str = unknown;
} else {
- dev_str = ambapp_device_id2str(vendor, deviceid);
+ dev_str = ambapp_device_id2str(dev->vendor, dev->device);
if (!dev_str)
dev_str = unknown;
}
- printf("0x%02x:0x%02x:0x%02x: %s %s\n"
+ /* Get Frequency of Core */
+ freq = ambapp_bus_freq(&ambapp_plb, dev->ahb_bus_index);
+
+ printf("0x%02x:0x%02x:0x%02x: %s %s (%dkHz)\n"
" apb: 0x%08x - 0x%08x\n"
" irq: %-2d (ver: %-2d)\n",
- index, vendor, deviceid, ven_str, dev_str, address,
- address + mask, irq, ver);
+ index, dev->vendor, dev->device, ven_str, dev_str, freq / 1000,
+ dev->address, dev->address + (dev->mask-1),
+ dev->irq, dev->ver);
}
-void ambapp_print_ahb(ahbctrl_pp_dev * ahb, int index)
+void ambapp_print_ahb(ambapp_ahbdev *dev, int index)
{
- char *dev_str, *ven_str;
- int irq, ver, vendor, deviceid;
- unsigned int addr, mask;
- int j;
+ char *dev_str, *ven_str, *type_str;
+ int i;
+ unsigned int freq;
- vendor = amba_vendor(ahb->conf);
- deviceid = amba_device(ahb->conf);
- irq = amba_irq(ahb->conf);
- ver = amba_ver(ahb->conf);
-
- ven_str = ambapp_vendor_id2str(vendor);
+ ven_str = ambapp_vendor_id2str(dev->vendor);
if (!ven_str) {
ven_str = unknown;
dev_str = unknown;
} else {
- dev_str = ambapp_device_id2str(vendor, deviceid);
+ dev_str = ambapp_device_id2str(dev->vendor, dev->device);
if (!dev_str)
dev_str = unknown;
}
- printf("0x%02x:0x%02x:0x%02x: %s %s\n",
- index, vendor, deviceid, ven_str, dev_str);
+ /* Get Frequency of Core */
+ freq = ambapp_bus_freq(&ambapp_plb, dev->ahb_bus_index);
+
+ printf("0x%02x:0x%02x:0x%02x: %s %s (%dkHz)\n",
+ index, dev->vendor, dev->device, ven_str, dev_str, freq / 1000);
- for (j = 0; j < 4; j++) {
- addr = amba_membar_start(ahb->bars[j]);
- if (amba_membar_type(ahb->bars[j]) == 0)
+ for (i = 0; i < 4; i++) {
+ if (dev->type[i] == 0)
continue;
- if (amba_membar_type(ahb->bars[j]) == AMBA_TYPE_AHBIO)
- addr = AMBA_TYPE_AHBIO_ADDR(addr);
- mask = amba_membar_mask(ahb->bars[j]) << 20;
- printf(" mem: 0x%08x - 0x%08x\n", addr, addr + ((~mask) + 1));
+ type_str = ambapp_type_names[dev->type[i]];
+ printf(" %-7s: 0x%08x - 0x%08x\n", type_str, dev->address[i],
+ dev->address[i] + (dev->mask[i]-1));
}
- printf(" irq: %-2d (ver: %d)\n", irq, ver);
+ printf(" irq: %-2d (ver: %d)\n", dev->irq, dev->ver);
}
int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
+ int index;
+ ambapp_apbdev apbdev;
+ ambapp_ahbdev ahbdev;
/* Print AHB Masters */
- puts("--------- AHB Masters ---------\n");
- ambapp_apb_print = 0;
- ambapp_ahb_print = 1;
- ambapp_ahbmst_count(99, 99); /* Get vendor&device 99 = nonexistent... */
+ puts("\n--------- AHB Masters ---------\n");
+ index = 0;
+ while (ambapp_ahbmst_find(&ambapp_plb, 0, 0, index, &ahbdev) == 1) {
+ /* Found a AHB Master Device */
+ ambapp_print_ahb(&ahbdev, index);
+ index++;
+ }
/* Print AHB Slaves */
- puts("--------- AHB Slaves ---------\n");
- ambapp_ahbslv_count(99, 99); /* Get vendor&device 99 = nonexistent... */
+ puts("\n--------- AHB Slaves ---------\n");
+ index = 0;
+ while (ambapp_ahbslv_find(&ambapp_plb, 0, 0, index, &ahbdev) == 1) {
+ /* Found a AHB Slave Device */
+ ambapp_print_ahb(&ahbdev, index);
+ index++;
+ }
/* Print APB Slaves */
- puts("--------- APB Slaves ---------\n");
- ambapp_apb_print = 1;
- ambapp_ahb_print = 0;
- ambapp_apb_count(99, 99); /* Get vendor&device 99 = nonexistent... */
-
- /* Reset, no futher printing */
- ambapp_apb_print = 0;
- ambapp_ahb_print = 0;
+ puts("\n--------- APB Slaves ---------\n");
+ index = 0;
+ while (ambapp_apb_find(&ambapp_plb, 0, 0, index, &apbdev) == 1) {
+ /* Found a APB Slave Device */
+ ambapp_print_apb(&apbdev, index);
+ index++;
+ }
+
puts("\n");
return 0;
}
@@ -240,16 +549,18 @@ int ambapp_init_reloc(void)
while (vend->vendor_id && vend->name) {
vend->name = (char *)((unsigned int)vend->name + gd->reloc_off);
- vend->devices =
- (ambapp_device_name *) ((unsigned int)vend->devices +
- gd->reloc_off);;
+ vend->desc = (char *)((unsigned int)vend->desc + gd->reloc_off);
+ vend->devices = (ambapp_device_name *)
+ ((unsigned int)vend->devices + gd->reloc_off);
dev = vend->devices;
vend++;
if (!dev)
continue;
while (dev->device_id && dev->name) {
dev->name =
- (char *)((unsigned int)dev->name + gd->reloc_off);;
+ (char *)((unsigned int)dev->name + gd->reloc_off);
+ dev->desc =
+ (char *)((unsigned int)dev->desc + gd->reloc_off);
dev++;
}
}
diff --git a/common/cmd_gpt.c b/common/cmd_gpt.c
index c56fe15d3b..e3c0297a1c 100644
--- a/common/cmd_gpt.c
+++ b/common/cmd_gpt.c
@@ -218,6 +218,23 @@ static int set_gpt_info(block_dev_desc_t *dev_desc,
strcpy((char *)parts[i].uuid, p);
free(val);
}
+#ifdef CONFIG_PARTITION_TYPE_GUID
+ /* guid */
+ val = extract_val(tok, "type");
+ if (val) {
+ /* 'type' is optional */
+ if (extract_env(val, &p))
+ p = val;
+ if (strlen(p) >= sizeof(parts[i].type_guid)) {
+ printf("Wrong type guid format for partition %d\n",
+ i);
+ errno = -4;
+ goto err;
+ }
+ strcpy((char *)parts[i].type_guid, p);
+ free(val);
+ }
+#endif
/* name */
val = extract_val(tok, "name");
if (!val) { /* name is mandatory */
diff --git a/common/fb_mmc.c b/common/fb_mmc.c
index 0c48cf929f..b480e76554 100644
--- a/common/fb_mmc.c
+++ b/common/fb_mmc.c
@@ -6,32 +6,24 @@
#include <config.h>
#include <common.h>
+#include <errno.h>
+#include <fastboot.h>
#include <fb_mmc.h>
+#include <image-sparse.h>
#include <part.h>
-#include <aboot.h>
#include <sparse_format.h>
#include <mmc.h>
+#include <div64.h>
#ifndef CONFIG_FASTBOOT_GPT_NAME
#define CONFIG_FASTBOOT_GPT_NAME GPT_ENTRY_NAME
#endif
-/* The 64 defined bytes plus the '\0' */
-#define RESPONSE_LEN (64 + 1)
-
static char *response_str;
-void fastboot_fail(const char *s)
-{
- strncpy(response_str, "FAIL\0", 5);
- strncat(response_str, s, RESPONSE_LEN - 4 - 1);
-}
-
-void fastboot_okay(const char *s)
-{
- strncpy(response_str, "OKAY\0", 5);
- strncat(response_str, s, RESPONSE_LEN - 4 - 1);
-}
+struct fb_mmc_sparse {
+ block_dev_desc_t *dev_desc;
+};
static int get_partition_info_efi_by_name_or_alias(block_dev_desc_t *dev_desc,
const char *name, disk_partition_t *info)
@@ -55,6 +47,24 @@ static int get_partition_info_efi_by_name_or_alias(block_dev_desc_t *dev_desc,
return ret;
}
+
+static int fb_mmc_sparse_write(struct sparse_storage *storage,
+ void *priv,
+ unsigned int offset,
+ unsigned int size,
+ char *data)
+{
+ struct fb_mmc_sparse *sparse = priv;
+ block_dev_desc_t *dev_desc = sparse->dev_desc;
+ int ret;
+
+ ret = dev_desc->block_write(dev_desc->dev, offset, size, data);
+ if (!ret)
+ return -EIO;
+
+ return ret;
+}
+
static void write_raw_image(block_dev_desc_t *dev_desc, disk_partition_t *info,
const char *part_name, void *buffer,
unsigned int download_bytes)
@@ -64,11 +74,11 @@ static void write_raw_image(block_dev_desc_t *dev_desc, disk_partition_t *info,
/* determine number of blocks to write */
blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1));
- blkcnt = blkcnt / info->blksz;
+ blkcnt = lldiv(blkcnt, info->blksz);
if (blkcnt > info->size) {
error("too large for partition: '%s'\n", part_name);
- fastboot_fail("too large for partition");
+ fastboot_fail(response_str, "too large for partition");
return;
}
@@ -78,17 +88,18 @@ static void write_raw_image(block_dev_desc_t *dev_desc, disk_partition_t *info,
buffer);
if (blks != blkcnt) {
error("failed writing to device %d\n", dev_desc->dev);
- fastboot_fail("failed writing to device");
+ fastboot_fail(response_str, "failed writing to device");
return;
}
printf("........ wrote " LBAFU " bytes to '%s'\n", blkcnt * info->blksz,
part_name);
- fastboot_okay("");
+ fastboot_okay(response_str, "");
}
-void fb_mmc_flash_write(const char *cmd, void *download_buffer,
- unsigned int download_bytes, char *response)
+void fb_mmc_flash_write(const char *cmd, unsigned int session_id,
+ void *download_buffer, unsigned int download_bytes,
+ char *response)
{
block_dev_desc_t *dev_desc;
disk_partition_t info;
@@ -99,7 +110,7 @@ void fb_mmc_flash_write(const char *cmd, void *download_buffer,
dev_desc = get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
error("invalid mmc device\n");
- fastboot_fail("invalid mmc device");
+ fastboot_fail(response_str, "invalid mmc device");
return;
}
@@ -109,29 +120,47 @@ void fb_mmc_flash_write(const char *cmd, void *download_buffer,
if (is_valid_gpt_buf(dev_desc, download_buffer)) {
printf("%s: invalid GPT - refusing to write to flash\n",
__func__);
- fastboot_fail("invalid GPT partition");
+ fastboot_fail(response_str, "invalid GPT partition");
return;
}
if (write_mbr_and_gpt_partitions(dev_desc, download_buffer)) {
printf("%s: writing GPT partitions failed\n", __func__);
- fastboot_fail("writing GPT partitions failed");
+ fastboot_fail(response_str,
+ "writing GPT partitions failed");
return;
}
printf("........ success\n");
- fastboot_okay("");
+ fastboot_okay(response_str, "");
return;
} else if (get_partition_info_efi_by_name_or_alias(dev_desc, cmd, &info)) {
error("cannot find partition: '%s'\n", cmd);
- fastboot_fail("cannot find partition");
+ fastboot_fail(response_str, "cannot find partition");
return;
}
- if (is_sparse_image(download_buffer))
- write_sparse_image(dev_desc, &info, cmd, download_buffer,
- download_bytes);
- else
+ if (is_sparse_image(download_buffer)) {
+ struct fb_mmc_sparse sparse_priv;
+ sparse_storage_t sparse;
+
+ sparse_priv.dev_desc = dev_desc;
+
+ sparse.block_sz = info.blksz;
+ sparse.start = info.start;
+ sparse.size = info.size;
+ sparse.name = cmd;
+ sparse.write = fb_mmc_sparse_write;
+
+ printf("Flashing sparse image at offset " LBAFU "\n",
+ info.start);
+
+ store_sparse_image(&sparse, &sparse_priv, session_id,
+ download_buffer);
+ } else {
write_raw_image(dev_desc, &info, cmd, download_buffer,
download_bytes);
+ }
+
+ fastboot_okay(response_str, "");
}
void fb_mmc_erase(const char *cmd, char *response)
@@ -144,7 +173,7 @@ void fb_mmc_erase(const char *cmd, char *response)
if (mmc == NULL) {
error("invalid mmc device");
- fastboot_fail("invalid mmc device");
+ fastboot_fail(response_str, "invalid mmc device");
return;
}
@@ -154,14 +183,14 @@ void fb_mmc_erase(const char *cmd, char *response)
dev_desc = get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
error("invalid mmc device");
- fastboot_fail("invalid mmc device");
+ fastboot_fail(response_str, "invalid mmc device");
return;
}
ret = get_partition_info_efi_by_name_or_alias(dev_desc, cmd, &info);
if (ret) {
error("cannot find partition: '%s'", cmd);
- fastboot_fail("cannot find partition");
+ fastboot_fail(response_str, "cannot find partition");
return;
}
@@ -180,11 +209,11 @@ void fb_mmc_erase(const char *cmd, char *response)
blks = dev_desc->block_erase(dev_desc->dev, blks_start, blks_size);
if (blks != blks_size) {
error("failed erasing from device %d", dev_desc->dev);
- fastboot_fail("failed erasing from device");
+ fastboot_fail(response_str, "failed erasing from device");
return;
}
printf("........ erased " LBAFU " bytes from '%s'\n",
blks_size * info.blksz, cmd);
- fastboot_okay("");
+ fastboot_okay(response_str, "");
}
diff --git a/common/fb_nand.c b/common/fb_nand.c
new file mode 100644
index 0000000000..9ca8602a73
--- /dev/null
+++ b/common/fb_nand.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2014 Broadcom Corporation.
+ * Copyright 2015 Free Electrons.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+
+#include <fastboot.h>
+#include <image-sparse.h>
+#include <sparse_format.h>
+
+#include <linux/mtd/mtd.h>
+#include <jffs2/jffs2.h>
+#include <nand.h>
+
+static char *response_str;
+
+struct fb_nand_sparse {
+ nand_info_t *nand;
+ struct part_info *part;
+};
+
+__weak int board_fastboot_erase_partition_setup(char *name)
+{
+ return 0;
+}
+
+__weak int board_fastboot_write_partition_setup(char *name)
+{
+ return 0;
+}
+
+static int fb_nand_lookup(const char *partname, char *response,
+ nand_info_t **nand,
+ struct part_info **part)
+{
+ struct mtd_device *dev;
+ int ret;
+ u8 pnum;
+
+ ret = mtdparts_init();
+ if (ret) {
+ error("Cannot initialize MTD partitions\n");
+ fastboot_fail(response_str, "cannot init mtdparts");
+ return ret;
+ }
+
+ ret = find_dev_and_part(partname, &dev, &pnum, part);
+ if (ret) {
+ error("cannot find partition: '%s'", partname);
+ fastboot_fail(response_str, "cannot find partition");
+ return ret;
+ }
+
+ if (dev->id->type != MTD_DEV_TYPE_NAND) {
+ error("partition '%s' is not stored on a NAND device",
+ partname);
+ fastboot_fail(response_str, "not a NAND device");
+ return -EINVAL;
+ }
+
+ *nand = &nand_info[dev->id->num];
+
+ return 0;
+}
+
+static int _fb_nand_erase(nand_info_t *nand, struct part_info *part)
+{
+ nand_erase_options_t opts;
+ int ret;
+
+ memset(&opts, 0, sizeof(opts));
+ opts.offset = part->offset;
+ opts.length = part->size;
+ opts.quiet = 1;
+
+ printf("Erasing blocks 0x%llx to 0x%llx\n",
+ part->offset, part->offset + part->size);
+
+ ret = nand_erase_opts(nand, &opts);
+ if (ret)
+ return ret;
+
+ printf("........ erased 0x%llx bytes from '%s'\n",
+ part->size, part->name);
+
+ return 0;
+}
+
+static int _fb_nand_write(nand_info_t *nand, struct part_info *part,
+ void *buffer, unsigned int offset,
+ unsigned int length, size_t *written)
+{
+ int flags = WITH_WR_VERIFY;
+
+#ifdef CONFIG_FASTBOOT_FLASH_NAND_TRIMFFS
+ flags |= WITH_DROP_FFS;
+#endif
+
+ return nand_write_skip_bad(nand, offset, &length, written,
+ part->size - (offset - part->offset),
+ buffer, flags);
+}
+
+static int fb_nand_sparse_write(struct sparse_storage *storage,
+ void *priv,
+ unsigned int offset,
+ unsigned int size,
+ char *data)
+{
+ struct fb_nand_sparse *sparse = priv;
+ size_t written;
+ int ret;
+
+ ret = _fb_nand_write(sparse->nand, sparse->part, data,
+ offset * storage->block_sz,
+ size * storage->block_sz, &written);
+ if (ret < 0) {
+ printf("Failed to write sparse chunk\n");
+ return ret;
+ }
+
+ return written / storage->block_sz;
+}
+
+void fb_nand_flash_write(const char *partname, unsigned int session_id,
+ void *download_buffer, unsigned int download_bytes,
+ char *response)
+{
+ struct part_info *part;
+ nand_info_t *nand = NULL;
+ int ret;
+
+ /* initialize the response buffer */
+ response_str = response;
+
+ ret = fb_nand_lookup(partname, response, &nand, &part);
+ if (ret) {
+ error("invalid NAND device");
+ fastboot_fail(response_str, "invalid NAND device");
+ return;
+ }
+
+ ret = board_fastboot_write_partition_setup(part->name);
+ if (ret)
+ return;
+
+ if (is_sparse_image(download_buffer)) {
+ struct fb_nand_sparse sparse_priv;
+ sparse_storage_t sparse;
+
+ sparse_priv.nand = nand;
+ sparse_priv.part = part;
+
+ sparse.block_sz = nand->writesize;
+ sparse.start = part->offset / sparse.block_sz;
+ sparse.size = part->size / sparse.block_sz;
+ sparse.name = part->name;
+ sparse.write = fb_nand_sparse_write;
+
+ ret = store_sparse_image(&sparse, &sparse_priv, session_id,
+ download_buffer);
+ } else {
+ printf("Flashing raw image at offset 0x%llx\n",
+ part->offset);
+
+ ret = _fb_nand_write(nand, part, download_buffer, part->offset,
+ download_bytes, NULL);
+
+ printf("........ wrote %u bytes to '%s'\n",
+ download_bytes, part->name);
+ }
+
+ if (ret) {
+ fastboot_fail(response_str, "error writing the image");
+ return;
+ }
+
+ fastboot_okay(response_str, "");
+}
+
+void fb_nand_erase(const char *partname, char *response)
+{
+ struct part_info *part;
+ nand_info_t *nand = NULL;
+ int ret;
+
+ /* initialize the response buffer */
+ response_str = response;
+
+ ret = fb_nand_lookup(partname, response, &nand, &part);
+ if (ret) {
+ error("invalid NAND device");
+ fastboot_fail(response_str, "invalid NAND device");
+ return;
+ }
+
+ ret = board_fastboot_erase_partition_setup(part->name);
+ if (ret)
+ return;
+
+ ret = _fb_nand_erase(nand, part);
+ if (ret) {
+ error("failed erasing from device %s", nand->name);
+ fastboot_fail(response_str, "failed erasing from device");
+ return;
+ }
+
+ fastboot_okay(response_str, "");
+}
diff --git a/common/image-sparse.c b/common/image-sparse.c
new file mode 100644
index 0000000000..dffe844d54
--- /dev/null
+++ b/common/image-sparse.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
+ * Portions Copyright 2014 Broadcom Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ *
+ * NOTE:
+ * Although it is very similar, this license text is not identical
+ * to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT!
+ */
+
+#include <config.h>
+#include <common.h>
+#include <div64.h>
+#include <errno.h>
+#include <image-sparse.h>
+#include <malloc.h>
+#include <part.h>
+#include <sparse_format.h>
+
+#include <linux/math64.h>
+
+typedef struct sparse_buffer {
+ void *data;
+ u32 length;
+ u32 repeat;
+ u16 type;
+} sparse_buffer_t;
+
+static uint32_t last_offset;
+
+static unsigned int sparse_get_chunk_data_size(sparse_header_t *sparse,
+ chunk_header_t *chunk)
+{
+ return chunk->total_sz - sparse->chunk_hdr_sz;
+}
+
+static unsigned int sparse_block_size_to_storage(unsigned int size,
+ sparse_storage_t *storage,
+ sparse_header_t *sparse)
+{
+ return size * sparse->blk_sz / storage->block_sz;
+}
+
+static bool sparse_chunk_has_buffer(chunk_header_t *chunk)
+{
+ switch (chunk->chunk_type) {
+ case CHUNK_TYPE_RAW:
+ case CHUNK_TYPE_FILL:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static sparse_header_t *sparse_parse_header(void **data)
+{
+ /* Read and skip over sparse image header */
+ sparse_header_t *sparse_header = (sparse_header_t *) *data;
+
+ *data += sparse_header->file_hdr_sz;
+
+ debug("=== Sparse Image Header ===\n");
+ debug("magic: 0x%x\n", sparse_header->magic);
+ debug("major_version: 0x%x\n", sparse_header->major_version);
+ debug("minor_version: 0x%x\n", sparse_header->minor_version);
+ debug("file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
+ debug("chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
+ debug("blk_sz: %d\n", sparse_header->blk_sz);
+ debug("total_blks: %d\n", sparse_header->total_blks);
+ debug("total_chunks: %d\n", sparse_header->total_chunks);
+
+ return sparse_header;
+}
+
+static int sparse_parse_fill_chunk(sparse_header_t *sparse,
+ chunk_header_t *chunk)
+{
+ unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
+
+ if (chunk_data_sz != sizeof(uint32_t))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int sparse_parse_raw_chunk(sparse_header_t *sparse,
+ chunk_header_t *chunk)
+{
+ unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
+
+ /* Check if the data size is a multiple of the main block size */
+ if (chunk_data_sz % sparse->blk_sz)
+ return -EINVAL;
+
+ /* Check that the chunk size is consistent */
+ if ((chunk_data_sz / sparse->blk_sz) != chunk->chunk_sz)
+ return -EINVAL;
+
+ return 0;
+}
+
+static chunk_header_t *sparse_parse_chunk(sparse_header_t *sparse,
+ void **image)
+{
+ chunk_header_t *chunk = (chunk_header_t *) *image;
+ int ret;
+
+ debug("=== Chunk Header ===\n");
+ debug("chunk_type: 0x%x\n", chunk->chunk_type);
+ debug("chunk_data_sz: 0x%x\n", chunk->chunk_sz);
+ debug("total_size: 0x%x\n", chunk->total_sz);
+
+ switch (chunk->chunk_type) {
+ case CHUNK_TYPE_RAW:
+ ret = sparse_parse_raw_chunk(sparse, chunk);
+ if (ret)
+ return NULL;
+ break;
+
+ case CHUNK_TYPE_FILL:
+ ret = sparse_parse_fill_chunk(sparse, chunk);
+ if (ret)
+ return NULL;
+ break;
+
+ case CHUNK_TYPE_DONT_CARE:
+ case CHUNK_TYPE_CRC32:
+ debug("Ignoring chunk\n");
+ break;
+
+ default:
+ printf("%s: Unknown chunk type: %x\n", __func__,
+ chunk->chunk_type);
+ return NULL;
+ }
+
+ *image += sparse->chunk_hdr_sz;
+
+ return chunk;
+}
+
+static int sparse_get_fill_buffer(sparse_header_t *sparse,
+ chunk_header_t *chunk,
+ sparse_buffer_t *buffer,
+ unsigned int blk_sz,
+ void *data)
+{
+ int i;
+
+ buffer->type = CHUNK_TYPE_FILL;
+
+ /*
+ * We create a buffer of one block, and ask it to be
+ * repeated as many times as needed.
+ */
+ buffer->length = blk_sz;
+ buffer->repeat = (chunk->chunk_sz * sparse->blk_sz) / blk_sz;
+
+ buffer->data = memalign(ARCH_DMA_MINALIGN,
+ ROUNDUP(blk_sz,
+ ARCH_DMA_MINALIGN));
+ if (!buffer->data)
+ return -ENOMEM;
+
+ for (i = 0; i < (buffer->length / sizeof(uint32_t)); i++)
+ ((uint32_t *)buffer->data)[i] = *(uint32_t *)(data);
+
+ return 0;
+}
+
+static int sparse_get_raw_buffer(sparse_header_t *sparse,
+ chunk_header_t *chunk,
+ sparse_buffer_t *buffer,
+ unsigned int blk_sz,
+ void *data)
+{
+ unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
+
+ buffer->type = CHUNK_TYPE_RAW;
+ buffer->length = chunk_data_sz;
+ buffer->data = data;
+ buffer->repeat = 1;
+
+ return 0;
+}
+
+static sparse_buffer_t *sparse_get_data_buffer(sparse_header_t *sparse,
+ chunk_header_t *chunk,
+ unsigned int blk_sz,
+ void **image)
+{
+ unsigned int chunk_data_sz = sparse_get_chunk_data_size(sparse, chunk);
+ sparse_buffer_t *buffer;
+ void *data = *image;
+ int ret;
+
+ *image += chunk_data_sz;
+
+ if (!sparse_chunk_has_buffer(chunk))
+ return NULL;
+
+ buffer = calloc(sizeof(sparse_buffer_t), 1);
+ if (!buffer)
+ return NULL;
+
+ switch (chunk->chunk_type) {
+ case CHUNK_TYPE_RAW:
+ ret = sparse_get_raw_buffer(sparse, chunk, buffer, blk_sz,
+ data);
+ if (ret)
+ return NULL;
+ break;
+
+ case CHUNK_TYPE_FILL:
+ ret = sparse_get_fill_buffer(sparse, chunk, buffer, blk_sz,
+ data);
+ if (ret)
+ return NULL;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ debug("=== Buffer ===\n");
+ debug("length: 0x%x\n", buffer->length);
+ debug("repeat: 0x%x\n", buffer->repeat);
+ debug("type: 0x%x\n", buffer->type);
+ debug("data: 0x%p\n", buffer->data);
+
+ return buffer;
+}
+
+static void sparse_put_data_buffer(sparse_buffer_t *buffer)
+{
+ if (buffer->type == CHUNK_TYPE_FILL)
+ free(buffer->data);
+
+ free(buffer);
+}
+
+int store_sparse_image(sparse_storage_t *storage, void *storage_priv,
+ unsigned int session_id, void *data)
+{
+ unsigned int chunk, offset;
+ sparse_header_t *sparse_header;
+ chunk_header_t *chunk_header;
+ sparse_buffer_t *buffer;
+ uint32_t start;
+ uint32_t total_blocks = 0;
+ uint32_t skipped = 0;
+ int i;
+
+ debug("=== Storage ===\n");
+ debug("name: %s\n", storage->name);
+ debug("block_size: 0x%x\n", storage->block_sz);
+ debug("start: 0x%x\n", storage->start);
+ debug("size: 0x%x\n", storage->size);
+ debug("write: 0x%p\n", storage->write);
+ debug("priv: 0x%p\n", storage_priv);
+
+ sparse_header = sparse_parse_header(&data);
+ if (!sparse_header) {
+ printf("sparse header issue\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Verify that the sparse block size is a multiple of our
+ * storage backend block size
+ */
+ div_u64_rem(sparse_header->blk_sz, storage->block_sz, &offset);
+ if (offset) {
+ printf("%s: Sparse image block size issue [%u]\n",
+ __func__, sparse_header->blk_sz);
+ return -EINVAL;
+ }
+
+ /*
+ * If it's a new flashing session, start at the beginning of
+ * the partition. If not, then simply resume where we were.
+ */
+ if (session_id > 0)
+ start = last_offset;
+ else
+ start = storage->start;
+
+ printf("Flashing sparse image on partition %s at offset 0x%x (ID: %d)\n",
+ storage->name, start * storage->block_sz, session_id);
+
+ /* Start processing chunks */
+ for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) {
+ uint32_t blkcnt;
+
+ chunk_header = sparse_parse_chunk(sparse_header, &data);
+ if (!chunk_header) {
+ printf("Unknown chunk type");
+ return -EINVAL;
+ }
+
+ /*
+ * If we have a DONT_CARE type, just skip the blocks
+ * and go on parsing the rest of the chunks
+ */
+ if (chunk_header->chunk_type == CHUNK_TYPE_DONT_CARE) {
+ skipped += sparse_block_size_to_storage(chunk_header->chunk_sz,
+ storage,
+ sparse_header);
+ continue;
+ }
+
+ /* Retrieve the buffer we're going to write */
+ buffer = sparse_get_data_buffer(sparse_header, chunk_header,
+ storage->block_sz, &data);
+ if (!buffer)
+ continue;
+
+ blkcnt = (buffer->length / storage->block_sz) * buffer->repeat;
+
+ if ((start + total_blocks + blkcnt) >
+ (storage->start + storage->size)) {
+ printf("%s: Request would exceed partition size!\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < buffer->repeat; i++) {
+ unsigned long buffer_blk_cnt;
+ int ret;
+
+ buffer_blk_cnt = buffer->length / storage->block_sz;
+
+ ret = storage->write(storage, storage_priv,
+ start + total_blocks,
+ buffer_blk_cnt,
+ buffer->data);
+ if (ret < 0) {
+ printf("%s: Write %d failed %d\n",
+ __func__, i, ret);
+ return ret;
+ }
+
+ total_blocks += ret;
+ }
+
+ sparse_put_data_buffer(buffer);
+ }
+
+ debug("Wrote %d blocks, skipped %d, expected to write %d blocks\n",
+ total_blocks, skipped,
+ sparse_block_size_to_storage(sparse_header->total_blks,
+ storage, sparse_header));
+ printf("........ wrote %d blocks to '%s'\n", total_blocks,
+ storage->name);
+
+ if ((total_blocks + skipped) !=
+ sparse_block_size_to_storage(sparse_header->total_blks,
+ storage, sparse_header)) {
+ printf("sparse image write failure\n");
+ return -EIO;
+ }
+
+ last_offset = start + total_blocks;
+
+ return 0;
+}
diff --git a/common/init/board_init.c b/common/init/board_init.c
index e74b63b8a8..1c6126d8ce 100644
--- a/common/init/board_init.c
+++ b/common/init/board_init.c
@@ -50,8 +50,7 @@ ulong board_init_f_mem(ulong top)
#endif
arch_setup_gd(gd_ptr);
-#if defined(CONFIG_SYS_MALLOC_F) && \
- (!defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SYS_SPL_MALLOC_START))
+#if defined(CONFIG_SYS_MALLOC_F)
top -= CONFIG_SYS_MALLOC_F_LEN;
gd->malloc_base = top;
#endif