diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 14 | ||||
-rw-r--r-- | common/Makefile | 7 | ||||
-rw-r--r-- | common/aboot.c | 244 | ||||
-rw-r--r-- | common/board_f.c | 7 | ||||
-rw-r--r-- | common/board_r.c | 24 | ||||
-rw-r--r-- | common/cmd_ambapp.c | 559 | ||||
-rw-r--r-- | common/cmd_gpt.c | 17 | ||||
-rw-r--r-- | common/fb_mmc.c | 99 | ||||
-rw-r--r-- | common/fb_nand.c | 213 | ||||
-rw-r--r-- | common/image-sparse.c | 393 | ||||
-rw-r--r-- | common/init/board_init.c | 3 |
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 |