master
Tom Rini 9 years ago
commit a851604ca3
  1. 1
      arch/arm/cpu/armv7/exynos/spl_boot.c
  2. 2
      arch/arm/cpu/armv7/omap-common/lowlevel_init.S
  3. 2
      arch/arm/cpu/armv7/omap3/lowlevel_init.S
  4. 7
      arch/arm/cpu/armv7/start.S
  5. 5
      arch/arm/cpu/armv7/sunxi/Makefile
  6. 46
      arch/arm/cpu/armv7/sunxi/board.c
  7. 2
      arch/arm/cpu/armv7/sunxi/config.mk
  8. 37
      arch/arm/cpu/armv7/sunxi/dram_helpers.c
  9. 42
      arch/arm/cpu/armv7/sunxi/fel_utils.S
  10. 82
      arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
  11. 28
      arch/arm/include/asm/arch-sunxi/dram.h
  12. 10
      arch/arm/include/asm/arch-sunxi/sys_proto.h
  13. 4
      arch/arm/include/asm/spl.h
  14. 15
      arch/arm/include/asm/system.h
  15. 3
      board/nokia/rx51/lowlevel_init.S
  16. 10
      board/sunxi/Kconfig
  17. 7
      board/sunxi/MAINTAINERS
  18. 5
      common/spl/spl.c
  19. 15
      configs/Ampe_A76_defconfig
  20. 13
      drivers/usb/musb-new/sunxi.c
  21. 36
      drivers/video/sunxi_display.c
  22. 14
      include/configs/sunxi-common.h
  23. 2
      scripts/Makefile.spl
  24. 14
      tools/mksunxiboot.c

@ -309,4 +309,3 @@ void board_init_r(gd_t *id, ulong dest_addr)
while (1)
;
}
void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {}

@ -19,7 +19,7 @@
ENTRY(save_boot_params)
ldr r1, =OMAP_SRAM_SCRATCH_BOOT_PARAMS
str r0, [r1]
bx lr
b save_boot_params_ret
ENDPROC(save_boot_params)
ENTRY(set_pl310_ctrl_reg)

@ -23,7 +23,7 @@ ENTRY(save_boot_params)
ldr r5, [r0, #0x4]
and r5, r5, #0xff
str r5, [r4]
bx lr
b save_boot_params_ret
ENDPROC(save_boot_params)
#endif

@ -31,9 +31,12 @@
*************************************************************************/
.globl reset
.globl save_boot_params_ret
reset:
bl save_boot_params
/* Allow the board to save important registers */
b save_boot_params
save_boot_params_ret:
/*
* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
* except if in HYP mode already
@ -96,7 +99,7 @@ ENDPROC(c_runtime_cpu_setup)
*
*************************************************************************/
ENTRY(save_boot_params)
bx lr @ back to my caller
b save_boot_params_ret @ back to my caller
ENDPROC(save_boot_params)
.weak save_boot_params

@ -11,6 +11,7 @@ obj-y += timer.o
obj-y += board.o
obj-y += clock.o
obj-y += cpu_info.o
obj-y += dram_helpers.o
obj-y += pinmux.o
obj-y += usbc.o
obj-$(CONFIG_MACH_SUN6I) += prcm.o
@ -38,7 +39,5 @@ obj-$(CONFIG_MACH_SUN5I) += dram_sun4i.o
obj-$(CONFIG_MACH_SUN6I) += dram_sun6i.o
obj-$(CONFIG_MACH_SUN7I) += dram_sun4i.o
obj-$(CONFIG_MACH_SUN8I) += dram_sun8i.o
ifdef CONFIG_SPL_FEL
obj-y += start.o
endif
obj-y += fel_utils.o
endif

@ -27,6 +27,17 @@
#include <linux/compiler.h>
struct fel_stash {
uint32_t sp;
uint32_t lr;
uint32_t cpsr;
uint32_t sctlr;
uint32_t vbar;
uint32_t cr;
};
struct fel_stash fel_stash __attribute__((section(".data")));
static int gpio_init(void)
{
#if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F)
@ -65,6 +76,12 @@ static int gpio_init(void)
return 0;
}
void spl_board_load_image(void)
{
debug("Returning to FEL sp=%x, lr=%x\n", fel_stash.sp, fel_stash.lr);
return_to_fel(fel_stash.sp, fel_stash.lr);
}
void s_init(void)
{
#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
@ -95,7 +112,34 @@ void s_init(void)
*/
u32 spl_boot_device(void)
{
return BOOT_DEVICE_MMC1;
#ifdef CONFIG_SPL_FEL
/*
* This is the legacy compile time configuration for a special FEL
* enabled build. It has many restrictions and can only boot over USB.
*/
return BOOT_DEVICE_BOARD;
#else
/*
* When booting from the SD card, the "eGON.BT0" signature is expected
* to be found in memory at the address 0x0004 (see the "mksunxiboot"
* tool, which generates this header).
*
* When booting in the FEL mode over USB, this signature is patched in
* memory and replaced with something else by the 'fel' tool. This other
* signature is selected in such a way, that it can't be present in a
* valid bootable SD card image (because the BROM would refuse to
* execute the SPL in this case).
*
* This branch is just making a decision at runtime whether to load
* the main u-boot binary from the SD card (if the "eGON.BT0" signature
* is found) or return to the FEL code in the BROM to wait and receive
* the main u-boot binary over USB.
*/
if (readl(4) == 0x4E4F4765 && readl(8) == 0x3054422E) /* eGON.BT0 */
return BOOT_DEVICE_MMC1;
else
return BOOT_DEVICE_BOARD;
#endif
}
/* No confirmation data available in SPL yet. Hardcode bootmode */

@ -1,8 +1,6 @@
# Build a combined spl + u-boot image
ifdef CONFIG_SPL
ifndef CONFIG_SPL_BUILD
ifndef CONFIG_SPL_FEL
ALL-y += u-boot-sunxi-with-spl.bin
endif
endif
endif

@ -0,0 +1,37 @@
/*
* DRAM init helper functions
*
* (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/dram.h>
/*
* Wait up to 1s for value to be set in given part of reg.
*/
void mctl_await_completion(u32 *reg, u32 mask, u32 val)
{
unsigned long tmo = timer_get_us() + 1000000;
while ((readl(reg) & mask) != val) {
if (timer_get_us() > tmo)
panic("Timeout initialising DRAM\n");
}
}
/*
* Test if memory at offset offset matches memory at begin of DRAM
*/
bool mctl_mem_matches(u32 offset)
{
/* Try to write different values to RAM at two addresses */
writel(0, CONFIG_SYS_SDRAM_BASE);
writel(0xaa55aa55, CONFIG_SYS_SDRAM_BASE + offset);
/* Check if the same value is actually observed when reading back */
return readl(CONFIG_SYS_SDRAM_BASE) ==
readl(CONFIG_SYS_SDRAM_BASE + offset);
}

@ -0,0 +1,42 @@
/*
* Utility functions for FEL mode.
*
* Copyright (c) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm-offsets.h>
#include <config.h>
#include <asm/system.h>
#include <linux/linkage.h>
ENTRY(save_boot_params)
ldr r0, =fel_stash
str sp, [r0, #0]
str lr, [r0, #4]
mrs lr, cpsr @ Read CPSR
str lr, [r0, #8]
mrc p15, 0, lr, c1, c0, 0 @ Read CP15 SCTLR Register
str lr, [r0, #12]
mrc p15, 0, lr, c12, c0, 0 @ Read VBAR
str lr, [r0, #16]
mrc p15, 0, lr, c1, c0, 0 @ Read CP15 Control Register
str lr, [r0, #20]
b save_boot_params_ret
ENDPROC(save_boot_params)
ENTRY(return_to_fel)
mov sp, r0
mov lr, r1
ldr r0, =fel_stash
ldr r1, [r0, #20]
mcr p15, 0, r1, c1, c0, 0 @ Write CP15 Control Register
ldr r1, [r0, #16]
mcr p15, 0, r1, c12, c0, 0 @ Write VBAR
ldr r1, [r0, #12]
mcr p15, 0, r1, c1, c0, 0 @ Write CP15 SCTLR Register
ldr r1, [r0, #8]
msr cpsr, r1 @ Write CPSR
bx lr
ENDPROC(return_to_fel)

@ -1,82 +0,0 @@
/*
* (C) Copyright 2013
* Henrik Nordstrom <henrik@henriknordstrom.net>
*
* SPDX-License-Identifier: GPL-2.0+
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(s_init)
SECTIONS
{
. = 0x00002000;
. = ALIGN(4);
.text :
{
*(.text.s_init)
*(.text*)
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : {
*(.data*)
}
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
. = ALIGN(4);
. = .;
. = ALIGN(4);
.rel.dyn : {
__rel_dyn_start = .;
*(.rel*)
__rel_dyn_end = .;
}
.dynsym : {
__dynsym_start = .;
*(.dynsym)
}
. = ALIGN(4);
.note.gnu.build-id :
{
*(.note.gnu.build-id)
}
_end = .;
. = ALIGN(4096);
.mmutable : {
*(.mmutable)
}
.bss_start __rel_dyn_start (OVERLAY) : {
KEEP(*(.__bss_start));
__bss_base = .;
}
.bss __bss_base (OVERLAY) : {
*(.bss*)
. = ALIGN(4);
__bss_limit = .;
}
.bss_end __bss_limit (OVERLAY) : {
KEEP(*(.__bss_end));
}
/DISCARD/ : { *(.dynstr*) }
/DISCARD/ : { *(.dynamic*) }
/DISCARD/ : { *(.plt*) }
/DISCARD/ : { *(.interp*) }
/DISCARD/ : { *(.gnu*) }
/DISCARD/ : { *(.note*) }
}

@ -25,31 +25,7 @@
#endif
unsigned long sunxi_dram_init(void);
/*
* Wait up to 1s for value to be set in given part of reg.
*/
static inline void mctl_await_completion(u32 *reg, u32 mask, u32 val)
{
unsigned long tmo = timer_get_us() + 1000000;
while ((readl(reg) & mask) != val) {
if (timer_get_us() > tmo)
panic("Timeout initialising DRAM\n");
}
}
/*
* Test if memory at offset offset matches memory at begin of DRAM
*/
static inline bool mctl_mem_matches(u32 offset)
{
/* Try to write different values to RAM at two addresses */
writel(0, CONFIG_SYS_SDRAM_BASE);
writel(0xaa55aa55, CONFIG_SYS_SDRAM_BASE + offset);
/* Check if the same value is actually observed when reading back */
return readl(CONFIG_SYS_SDRAM_BASE) ==
readl(CONFIG_SYS_SDRAM_BASE + offset);
}
void mctl_await_completion(u32 *reg, u32 mask, u32 val);
bool mctl_mem_matches(u32 offset);
#endif /* _SUNXI_DRAM_H */

@ -13,4 +13,14 @@
void sdelay(unsigned long);
/* return_to_fel() - Return to BROM from SPL
*
* This returns back into the BROM after U-Boot SPL has performed its initial
* init. It uses the provided lr and sp to do so.
*
* @lr: BROM link register value (return address)
* @sp: BROM stack pointer
*/
void return_to_fel(uint32_t lr, uint32_t sp);
#endif

@ -26,10 +26,14 @@ enum {
BOOT_DEVICE_SPI,
BOOT_DEVICE_SATA,
BOOT_DEVICE_I2C,
BOOT_DEVICE_BOARD,
BOOT_DEVICE_NONE
};
#endif
/* Board-specific load method */
void spl_board_load_image(void);
/* Linker symbols. */
extern char __bss_start[], __bss_end[];

@ -142,6 +142,21 @@ void flush_l3_cache(void);
#ifndef __ASSEMBLY__
/**
* save_boot_params() - Save boot parameters before starting reset sequence
*
* If you provide this function it will be called immediately U-Boot starts,
* both for SPL and U-Boot proper.
*
* All registers are unchanged from U-Boot entry. No registers need be
* preserved.
*
* This is not a normal C function. There is no stack. Return by branching to
* save_boot_params_ret.
*
* void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3);
*/
#define isb() __asm__ __volatile__ ("" : : : "memory")
#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");

@ -37,7 +37,8 @@ ih_magic: /* IH_MAGIC in big endian from include/image.h */
.global save_boot_params
save_boot_params:
/* Get return address */
ldr lr, =save_boot_params_ret
/* Copy valid attached kernel to address KERNEL_ADDRESS */

@ -149,6 +149,16 @@ config SPL_FEL
bool "SPL/FEL mode support"
depends on SPL
default n
help
This enables support for Fast Early Loader (FEL) mode. This
allows U-Boot to be loaded to the board over USB by the on-chip
boot rom. U-Boot should be sent in two parts: SPL first, with
'fel write 0x2000 u-boot-spl.bin; fel exe 0x2000' then U-Boot with
'fel write 0x4a000000 u-boot.bin; fel exe 0x4a000000'. This option
shrinks the amount of SRAM available to SPL, so only enable it if
you need FEL. Note that enabling this option only allows FEL to be
used; it is still possible to boot U-Boot from boot media. U-Boot
SPL detects when it is being loaded using FEL.
config UART0_PORT_F
bool "UART0 on MicroSD breakout board"

@ -46,6 +46,11 @@ S: Maintained
F: board/sunxi/dram_a20_olinuxino_l2.c
F: configs/A20-OLinuXino-Lime2_defconfig
AMPE A76 BOARD
M: Paul Kocialkowski <contact@paulk.fr>
S: Maintained
F: configs/Ampe_A76_defconfig
COLOMBUS BOARD
M: Maxime Ripard <maxime.ripard@free-electrons.com>
S: Maintained
@ -57,9 +62,7 @@ M: Hans de Goede <hdegoede@redhat.com>
S: Maintained
F: include/configs/sun7i.h
F: configs/Cubieboard2_defconfig
F: configs/Cubieboard2_FEL_defconfig
F: configs/Cubietruck_defconfig
F: configs/Cubietruck_FEL_defconfig
GEMEI-G9 TABLET
M: Priit Laes <plaes@plaes.org>

@ -229,6 +229,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
spl_sata_load_image();
break;
#endif
#ifdef CONFIG_SPL_BOARD_LOAD_IMAGE
case BOOT_DEVICE_BOARD:
spl_board_load_image();
break;
#endif
default:
#if defined(CONFIG_SPL_SERIAL_SUPPORT) && defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
puts("SPL: Unsupported Boot Device!\n");

@ -0,0 +1,15 @@
CONFIG_SPL=y
CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=2,AXP209_POWER"
CONFIG_FDTFILE="sun5i-a13-ampe-a76.dtb"
CONFIG_USB_MUSB_SUNXI=y
CONFIG_USB0_VBUS_PIN="PG12"
CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:45,ri:82,up:22,lo:22,hs:1,vs:1,sync:3,vmode:0"
CONFIG_VIDEO_LCD_POWER="AXP0-0"
CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
CONFIG_VIDEO_LCD_BL_PWM="PB2"
+S:CONFIG_ARM=y
+S:CONFIG_ARCH_SUNXI=y
+S:CONFIG_MACH_SUN5I=y
+S:CONFIG_DRAM_CLK=432
+S:CONFIG_DRAM_ZQ=123
+S:CONFIG_DRAM_EMR1=4

@ -145,16 +145,6 @@ static void USBC_ForceIdToHigh(__iomem void *base)
musb_writel(base, USBC_REG_o_ISCR, reg_val);
}
static void USBC_ForceVbusValidDisable(__iomem void *base)
{
u32 reg_val;
reg_val = musb_readl(base, USBC_REG_o_ISCR);
reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID);
reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
musb_writel(base, USBC_REG_o_ISCR, reg_val);
}
static void USBC_ForceVbusValidToHigh(__iomem void *base)
{
u32 reg_val;
@ -248,12 +238,11 @@ static int sunxi_musb_init(struct musb *musb)
if (is_host_enabled(musb)) {
/* Host mode */
USBC_ForceIdToLow(musb->mregs);
USBC_ForceVbusValidToHigh(musb->mregs);
} else {
/* Peripheral mode */
USBC_ForceIdToHigh(musb->mregs);
USBC_ForceVbusValidDisable(musb->mregs);
}
USBC_ForceVbusValidToHigh(musb->mregs);
return 0;
}

@ -46,6 +46,7 @@ struct sunxi_display {
GraphicDevice graphic_device;
enum sunxi_monitor monitor;
unsigned int depth;
unsigned int fb_size;
} sunxi_display;
#ifdef CONFIG_VIDEO_HDMI
@ -1060,6 +1061,11 @@ static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
return NULL; /* never reached */
}
ulong board_get_usable_ram_top(ulong total_size)
{
return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
}
void *video_hw_init(void)
{
static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
@ -1075,10 +1081,6 @@ void *video_hw_init(void)
memset(&sunxi_display, 0, sizeof(struct sunxi_display));
printf("Reserved %dkB of RAM for Framebuffer.\n",
CONFIG_SUNXI_FB_SIZE >> 10);
gd->fb_base = gd->ram_top;
video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
&sunxi_display.depth, &options);
#ifdef CONFIG_VIDEO_HDMI
@ -1169,6 +1171,17 @@ void *video_hw_init(void)
mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));
}
sunxi_display.fb_size =
(mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
printf("Error need %dkB for fb, but only %dkB is reserved\n",
sunxi_display.fb_size >> 10,
CONFIG_SUNXI_MAX_FB_SIZE >> 10);
return NULL;
}
gd->fb_base = gd->bd->bi_dram[0].start +
gd->bd->bi_dram[0].size - sunxi_display.fb_size;
sunxi_engines_init();
sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
@ -1194,6 +1207,7 @@ int sunxi_simplefb_setup(void *blob)
{
static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
int offset, ret;
u64 start, size;
const char *pipeline = NULL;
#ifdef CONFIG_MACH_SUN4I
@ -1237,6 +1251,20 @@ int sunxi_simplefb_setup(void *blob)
return 0; /* Keep older kernels working */
}
/*
* Do not report the framebuffer as free RAM to the OS, note we cannot
* use fdt_add_mem_rsv() here, because then it is still seen as RAM,
* and e.g. Linux refuses to iomap RAM on ARM, see:
* linux/arch/arm/mm/ioremap.c around line 301.
*/
start = gd->bd->bi_dram[0].start;
size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
if (ret) {
eprintf("Cannot setup simplefb: Error reserving memory\n");
return ret;
}
ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base,
graphic_device->winSizeX, graphic_device->winSizeY,
graphic_device->winSizeX * graphic_device->gdfBytesPP,

@ -18,10 +18,8 @@
*/
#define CONFIG_SUNXI /* sunxi family */
#ifdef CONFIG_SPL_BUILD
#ifndef CONFIG_SPL_FEL
#define CONFIG_SYS_THUMB_BUILD /* Thumbs mode to save space in SPL */
#endif
#endif
#include <asm/arch/cpu.h> /* get chip and board defs */
@ -145,10 +143,10 @@
#define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_LIBGENERIC_SUPPORT
#define CONFIG_SPL_BOARD_LOAD_IMAGE
#ifdef CONFIG_SPL_FEL
#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds"
#define CONFIG_SPL_START_S_PATH "arch/arm/cpu/armv7/sunxi"
#define CONFIG_SPL_TEXT_BASE 0x2000
#define CONFIG_SPL_MAX_SIZE 0x4000 /* 16 KiB */
@ -206,10 +204,10 @@
#ifdef CONFIG_VIDEO
/*
* The amount of RAM that is reserved for the FB. This will not show up as
* RAM to the kernel, but will be reclaimed by a KMS driver in future.
* The amount of RAM to keep free at the top of RAM when relocating u-boot,
* to use as framebuffer. This must be a multiple of 4096.
*/
#define CONFIG_SUNXI_FB_SIZE (9 << 20)
#define CONFIG_SUNXI_MAX_FB_SIZE (9 << 20)
/* Do we want to initialize a simple FB? */
#define CONFIG_VIDEO_DT_SIMPLEFB
@ -227,8 +225,6 @@
/* stop x86 thinking in cfbconsole from trying to init a pc keyboard */
#define CONFIG_VGA_AS_SINGLE_DEVICE
#define CONFIG_SYS_MEM_TOP_HIDE ((CONFIG_SUNXI_FB_SIZE + 0xFFF) & ~0xFFF)
/* To be able to hook simplefb into dt */
#ifdef CONFIG_VIDEO_DT_SIMPLEFB
#define CONFIG_OF_BOARD_SETUP

@ -154,10 +154,8 @@ ALL-y += $(obj)/$(BOARD)-spl.bin
endif
ifdef CONFIG_SUNXI
ifndef CONFIG_SPL_FEL
ALL-y += $(obj)/sunxi-spl.bin
endif
endif
ifeq ($(CONFIG_SYS_SOC),"at91")
ALL-y += boot.bin

@ -43,19 +43,19 @@ int gen_check_sum(struct boot_file_head *head_p)
uint32_t i;
uint32_t sum;
length = head_p->length;
length = le32_to_cpu(head_p->length);
if ((length & 0x3) != 0) /* must 4-byte-aligned */
return -1;
buf = (uint32_t *)head_p;
head_p->check_sum = STAMP_VALUE; /* fill stamp */
head_p->check_sum = cpu_to_le32(STAMP_VALUE); /* fill stamp */
loop = length >> 2;
/* calculate the sum */
for (i = 0, sum = 0; i < loop; i++)
sum += buf[i];
sum += le32_to_cpu(buf[i]);
/* write back check sum */
head_p->check_sum = sum;
head_p->check_sum = cpu_to_le32(sum);
return 0;
}
@ -125,10 +125,12 @@ int main(int argc, char *argv[])
memcpy(img.header.magic, BOOT0_MAGIC, 8); /* no '0' termination */
img.header.length =
ALIGN(file_size + sizeof(struct boot_file_head), BLOCK_SIZE);
img.header.b_instruction = cpu_to_le32(img.header.b_instruction);
img.header.length = cpu_to_le32(img.header.length);
gen_check_sum(&img.header);
count = write(fd_out, &img, img.header.length);
if (count != img.header.length) {
count = write(fd_out, &img, le32_to_cpu(img.header.length));
if (count != le32_to_cpu(img.header.length)) {
perror("Writing output");
return EXIT_FAILURE;
}

Loading…
Cancel
Save