diff --git a/.mailmap b/.mailmap index b76f02283c57ed82a9a0e0743a9f01102a08f1c8..3d15a09d1c2defe44ce785a35482cf3ce2cb6414 100644 --- a/.mailmap +++ b/.mailmap @@ -29,6 +29,7 @@ Jagan Teki Jagan Teki Jagan Teki Jagan Teki +Jernej Skrabec Igor Opaniuk Igor Opaniuk Markus Klotzbuecher diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c815ad461a8ccff9ae19c72b198169460d4fd743..47f094514b037c7e262708fd534373b9f9fe6920 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -9,9 +9,9 @@ config ARM64 select PHYS_64BIT select SYS_CACHE_SHIFT_6 -if ARM64 config POSITION_INDEPENDENT bool "Generate position-independent pre-relocation code" + depends on ARM64 || CPU_V7A help U-Boot expects to be linked to a specific hard-coded address, and to be loaded to and run from that address. This option lifts that @@ -22,6 +22,7 @@ config POSITION_INDEPENDENT config INIT_SP_RELATIVE bool "Specify the early stack pointer relative to the .bss section" + depends on ARM64 default n if ARCH_QEMU default y if POSITION_INDEPENDENT help @@ -37,6 +38,7 @@ config INIT_SP_RELATIVE config SYS_INIT_SP_BSS_OFFSET int "Early stack offset from the .bss base address" + depends on ARM64 depends on INIT_SP_RELATIVE default 524288 help @@ -46,6 +48,7 @@ config SYS_INIT_SP_BSS_OFFSET do not overlap any appended DTB. config LINUX_KERNEL_IMAGE_HEADER + depends on ARM64 bool help Place a Linux kernel image header at the start of the U-Boot binary. @@ -54,14 +57,12 @@ config LINUX_KERNEL_IMAGE_HEADER image header reports the amount of memory (BSS and similar) that U-Boot needs to use, but which isn't part of the binary. -if LINUX_KERNEL_IMAGE_HEADER config LNX_KRNL_IMG_TEXT_OFFSET_BASE + depends on LINUX_KERNEL_IMAGE_HEADER hex help The value subtracted from CONFIG_SYS_TEXT_BASE to calculate the TEXT_OFFSET value written to the Linux kernel image header. -endif -endif config GICV2 bool @@ -1184,6 +1185,13 @@ config TARGET_VEXPRESS64_BASE_FVP select PL01X_SERIAL select SEMIHOSTING +config TARGET_VEXPRESS64_BASER_FVP + bool "Support Versatile Express ARMv8r64 FVP BASE model" + select ARM64 + select DM + select DM_SERIAL + select PL01X_SERIAL + config TARGET_VEXPRESS64_JUNO bool "Support Versatile Express Juno Development Platform" select ARM64 diff --git a/arch/arm/config.mk b/arch/arm/config.mk index b684d8b416f77641fdcaa0a28c0e39e195fc8d9f..b107b1af27ac07571144532eda80fb86c9b223c1 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -25,6 +25,7 @@ endif PLATFORM_RELFLAGS += -fno-common -ffixed-r9 PLATFORM_RELFLAGS += $(call cc-option, -msoft-float) \ + $(call cc-option,-mgeneral-regs-only) \ $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) # LLVM support diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S index 87329d26e104a96c98ae7bbf22dbc4b9d3cc1614..698e15b8e184da24ff61ba82862086521ade16c0 100644 --- a/arch/arm/cpu/armv7/start.S +++ b/arch/arm/cpu/armv7/start.S @@ -39,6 +39,42 @@ reset: /* Allow the board to save important registers */ b save_boot_params save_boot_params_ret: +#ifdef CONFIG_POSITION_INDEPENDENT + /* + * Fix .rela.dyn relocations. This allows U-Boot to loaded to and + * executed at a different address than it was linked at. + */ +pie_fixup: + adr r0, reset /* r0 <- Runtime value of reset label */ + ldr r1, =reset /* r1 <- Linked value of reset label */ + subs r4, r0, r1 /* r4 <- Runtime-vs-link offset */ + beq pie_fixup_done + + adr r0, pie_fixup + ldr r1, _rel_dyn_start_ofs + add r2, r0, r1 /* r2 <- Runtime &__rel_dyn_start */ + ldr r1, _rel_dyn_end_ofs + add r3, r0, r1 /* r3 <- Runtime &__rel_dyn_end */ + +pie_fix_loop: + ldr r0, [r2] /* r0 <- Link location */ + ldr r1, [r2, #4] /* r1 <- fixup */ + cmp r1, #23 /* relative fixup? */ + bne pie_skip_reloc + + /* relative fix: increase location by offset */ + add r0, r4 + ldr r1, [r0] + add r1, r4 + str r1, [r0] + str r0, [r2] + add r2, #8 +pie_skip_reloc: + cmp r2, r3 + blo pie_fix_loop +pie_fixup_done: +#endif + #ifdef CONFIG_ARMV7_LPAE /* * check for Hypervisor support @@ -340,3 +376,10 @@ ENTRY(cpu_init_crit) b lowlevel_init @ go setup pll,mux,memory ENDPROC(cpu_init_crit) #endif + +#if CONFIG_POSITION_INDEPENDENT +_rel_dyn_start_ofs: + .word __rel_dyn_start - pie_fixup +_rel_dyn_end_ofs: + .word __rel_dyn_end - pie_fixup +#endif diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index 3de18c7675b9eb9a6e496b0cd849a10f1909fd66..46625675bddc5f9685556eabf5bae8d192d55534 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -15,6 +15,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -365,6 +366,86 @@ __weak u64 get_page_table_size(void) return size; } +static void mpu_clear_regions(void) +{ + int i; + + for (i = 0; mpu_mem_map[i].end || mpu_mem_map[i].attrs; i++) { + setup_el2_mpu_region(i, 0, 0); + } +} + +static struct mpu_region default_mpu_mem_map[] = {{0,}}; +__weak struct mpu_region *mpu_mem_map = default_mpu_mem_map; + +static void mpu_setup(void) +{ + int i; + + if (current_el() != 2) { + panic("MPU configuration is only supported at EL2"); + } + + set_sctlr(get_sctlr() & ~(CR_M | CR_WXN)); + + asm volatile("msr MAIR_EL2, %0" : : "r" MEMORY_ATTRIBUTES); + + for (i = 0; mpu_mem_map[i].end || mpu_mem_map[i].attrs; i++) { + setup_el2_mpu_region(i, + PRBAR_ADDRESS(mpu_mem_map[i].start) + | PRBAR_OUTER_SH | PRBAR_AP_RW_ANY, + PRLAR_ADDRESS(mpu_mem_map[i].end) + | mpu_mem_map[i].attrs | PRLAR_EN_BIT + ); + } + + set_sctlr(get_sctlr() | CR_M); +} + +static bool el_has_mmu(void) +{ + uint64_t id_aa64mmfr0; + asm volatile("mrs %0, id_aa64mmfr0_el1" + : "=r" (id_aa64mmfr0) : : "cc"); + uint64_t msa = id_aa64mmfr0 & ID_AA64MMFR0_EL1_MSA_MASK; + uint64_t msa_frac = id_aa64mmfr0 & ID_AA64MMFR0_EL1_MSA_FRAC_MASK; + + switch (msa) { + case ID_AA64MMFR0_EL1_MSA_VMSA: + /* + * VMSA supported in all translation regimes. + * No support for PMSA. + */ + return true; + case ID_AA64MMFR0_EL1_MSA_USE_FRAC: + /* See MSA_frac for the supported MSAs. */ + switch (msa_frac) { + case ID_AA64MMFR0_EL1_MSA_FRAC_NO_PMSA: + /* + * PMSA not supported in any translation + * regime. + */ + return true; + case ID_AA64MMFR0_EL1_MSA_FRAC_VMSA: + /* + * PMSA supported in all translation + * regimes. No support for VMSA. + */ + case ID_AA64MMFR0_EL1_MSA_FRAC_PMSA: + /* + * PMSA supported in all translation + * regimes. + */ + return false; + default: + panic("Unsupported id_aa64mmfr0_el1 " \ + "MSA_frac value"); + } + default: + panic("Unsupported id_aa64mmfr0_el1 MSA value"); + } +} + void setup_pgtables(void) { int i; @@ -479,8 +560,13 @@ void dcache_enable(void) /* The data cache is not active unless the mmu is enabled */ if (!(get_sctlr() & CR_M)) { invalidate_dcache_all(); - __asm_invalidate_tlb_all(); - mmu_setup(); + + if (el_has_mmu()) { + __asm_invalidate_tlb_all(); + mmu_setup(); + } else { + mpu_setup(); + } } set_sctlr(get_sctlr() | CR_C); @@ -499,7 +585,11 @@ void dcache_disable(void) set_sctlr(sctlr & ~(CR_C|CR_M)); flush_dcache_all(); - __asm_invalidate_tlb_all(); + + if (el_has_mmu()) + __asm_invalidate_tlb_all(); + else + mpu_clear_regions(); } int dcache_status(void) diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spintable.S b/arch/arm/cpu/armv8/fsl-layerscape/spintable.S index 363ded03e603c8461b81eb38fb8e344e1b4ffc2f..d6bd1884599c43f35d15b6fbb686ba7f2cf6ec6c 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/spintable.S +++ b/arch/arm/cpu/armv8/fsl-layerscape/spintable.S @@ -93,7 +93,7 @@ __secondary_boot_func: 4: #ifdef CONFIG_ARMV8_SWITCH_TO_EL1 switch_el x7, _dead_loop, 0f, _dead_loop -0: armv8_switch_to_el1_m x4, x6, x7 +0: armv8_switch_to_el1_m x4, x6, x7, x9 #else switch_el x7, 0f, _dead_loop, _dead_loop 0: armv8_switch_to_el2_m x4, x6, x7 diff --git a/arch/arm/cpu/armv8/transition.S b/arch/arm/cpu/armv8/transition.S index a31af4ffc8943af6aea86f24babcbcf8eeb3b1ae..9dbdff3a4fceaba29a62f8c79db031fac97435af 100644 --- a/arch/arm/cpu/armv8/transition.S +++ b/arch/arm/cpu/armv8/transition.S @@ -40,7 +40,7 @@ ENTRY(armv8_switch_to_el1) * now, jump to the address saved in x4. */ br x4 -1: armv8_switch_to_el1_m x4, x5, x6 +1: armv8_switch_to_el1_m x4, x5, x6, x7 ENDPROC(armv8_switch_to_el1) .popsection diff --git a/arch/arm/include/asm/armv8/mpu.h b/arch/arm/include/asm/armv8/mpu.h new file mode 100644 index 0000000000000000000000000000000000000000..c6c8828325e63390438d0171d9310eb2cec7cd05 --- /dev/null +++ b/arch/arm/include/asm/armv8/mpu.h @@ -0,0 +1,61 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + * + * (C) Copyright 2021 Arm Limited + */ + +#ifndef _ASM_ARMV8_MPU_H_ +#define _ASM_ARMV8_MPU_H_ + +#include +#include +#include + +#define PRSELR_EL2 S3_4_c6_c2_1 +#define PRBAR_EL2 S3_4_c6_c8_0 +#define PRLAR_EL2 S3_4_c6_c8_1 +#define MPUIR_EL2 S3_4_c0_c0_4 + +#define PRBAR_ADDRESS(addr) ((addr) & ~(0x3fULL)) + +/* Access permissions */ +#define PRBAR_AP(val) (((val) & 0x3) << 2) +#define PRBAR_AP_RW_HYP PRBAR_AP(0x0) +#define PRBAR_AP_RW_ANY PRBAR_AP(0x1) +#define PRBAR_AP_RO_HYP PRBAR_AP(0x2) +#define PRBAR_AP_RO_ANY PRBAR_AP(0x3) + +/* Shareability */ +#define PRBAR_SH(val) (((val) & 0x3) << 4) +#define PRBAR_NON_SH PRBAR_SH(0x0) +#define PRBAR_OUTER_SH PRBAR_SH(0x2) +#define PRBAR_INNER_SH PRBAR_SH(0x3) + +/* Memory attribute (MAIR idx) */ +#define PRLAR_ATTRIDX(val) (((val) & 0x7) << 1) +#define PRLAR_EN_BIT (0x1) +#define PRLAR_ADDRESS(addr) ((addr) & ~(0x3fULL)) + +#ifndef __ASSEMBLY__ + +static inline void setup_el2_mpu_region(uint8_t region, uint64_t base, uint64_t limit) +{ + asm volatile("msr " __stringify(PRSELR_EL2) ", %0" : : "r" (region)); + isb(); + asm volatile("msr " __stringify(PRBAR_EL2) ", %0" : : "r" (base)); + asm volatile("msr " __stringify(PRLAR_EL2) ", %0" : : "r" (limit)); + dsb(); + isb(); +} + +#endif + +struct mpu_region { + u64 start; + u64 end; + u64 attrs; +}; + +extern struct mpu_region *mpu_mem_map; + +#endif /* _ASM_ARMV8_MPU_H_ */ diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h index 485310d66086de326810355be02de177ccfe55fa..ecd8221c0dd41671c9d1783a63f0f214e3300cff 100644 --- a/arch/arm/include/asm/macro.h +++ b/arch/arm/include/asm/macro.h @@ -256,7 +256,7 @@ lr .req x30 * For loading 64-bit OS, x0 is physical address to the FDT blob. * They will be passed to the guest. */ -.macro armv8_switch_to_el1_m, ep, flag, tmp +.macro armv8_switch_to_el1_m, ep, flag, tmp, tmp2 /* Initialize Generic Timers */ mrs \tmp, cnthctl_el2 /* Enable EL1 access to timers */ @@ -306,9 +306,33 @@ lr .req x30 b.eq 1f /* Initialize HCR_EL2 */ - ldr \tmp, =(HCR_EL2_RW_AARCH64 | HCR_EL2_HCD_DIS) + /* Only disable PAuth traps if PAuth is supported */ + mrs \tmp, id_aa64isar1_el1 + ldr \tmp2, =(ID_AA64ISAR1_EL1_GPI | ID_AA64ISAR1_EL1_GPA | \ + ID_AA64ISAR1_EL1_API | ID_AA64ISAR1_EL1_APA) + tst \tmp, \tmp2 + mov \tmp2, #(HCR_EL2_RW_AARCH64 | HCR_EL2_HCD_DIS) + orr \tmp, \tmp2, #(HCR_EL2_APK | HCR_EL2_API) + csel \tmp, \tmp2, \tmp, eq msr hcr_el2, \tmp + /* + * Detect whether the system has a configurable memory system + * architecture at EL1&0 + */ + mrs \tmp, id_aa64mmfr0_el1 + lsr \tmp, \tmp, #48 + and \tmp, \tmp, #((ID_AA64MMFR0_EL1_MSA_MASK | \ + ID_AA64MMFR0_EL1_MSA_FRAC_MASK) >> 48) + cmp \tmp, #((ID_AA64MMFR0_EL1_MSA_USE_FRAC | \ + ID_AA64MMFR0_EL1_MSA_FRAC_VMSA) >> 48) + bne 2f + + /* Ensure the EL1&0 VMSA is enabled */ + mov \tmp, #(VTCR_EL2_MSA) + msr vtcr_el2, \tmp +2: + /* Return to the EL1_SP1 mode from EL2 */ ldr \tmp, =(SPSR_EL_DEBUG_MASK | SPSR_EL_SERR_MASK |\ SPSR_EL_IRQ_MASK | SPSR_EL_FIQ_MASK |\ diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 8b3a54e64c82ae9ddf4141aaa8f22c034dfc16ac..1ec6237320b0ac6ecf73b1bb5bee03d6e2fb9372 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -75,10 +75,49 @@ /* * HCR_EL2 bits definitions */ +#define HCR_EL2_API (1 << 41) /* Trap pointer authentication + instructions */ +#define HCR_EL2_APK (1 << 40) /* Trap pointer authentication + key access */ #define HCR_EL2_RW_AARCH64 (1 << 31) /* EL1 is AArch64 */ #define HCR_EL2_RW_AARCH32 (0 << 31) /* Lower levels are AArch32 */ #define HCR_EL2_HCD_DIS (1 << 29) /* Hypervisor Call disabled */ +/* + * VTCR_EL2 bits definitions + */ +#define VTCR_EL2_MSA (1 << 31) /* EL1&0 memory architecture */ + +/* + * ID_AA64MMFR0_EL1 bits definitions + */ +#define ID_AA64MMFR0_EL1_MSA_FRAC_MASK (0xFUL << 52) /* Memory system + architecture + frac */ +#define ID_AA64MMFR0_EL1_MSA_FRAC_VMSA (0x2UL << 52) /* EL1&0 supports + VMSA */ +#define ID_AA64MMFR0_EL1_MSA_FRAC_PMSA (0x1UL << 52) /* EL1&0 only + supports PMSA*/ +#define ID_AA64MMFR0_EL1_MSA_FRAC_NO_PMSA (0x0UL << 52) /* No PMSA + support */ +#define ID_AA64MMFR0_EL1_MSA_MASK (0xFUL << 48) /* Memory system + architecture */ +#define ID_AA64MMFR0_EL1_MSA_USE_FRAC (0xFUL << 48) /* Use MSA_FRAC */ +#define ID_AA64MMFR0_EL1_MSA_VMSA (0x0UL << 48) /* Memory system + architecture + is VMSA */ + +/* + * ID_AA64ISAR1_EL1 bits definitions + */ +#define ID_AA64ISAR1_EL1_GPI (0xF << 28) /* Implementation-defined generic + code auth algorithm */ +#define ID_AA64ISAR1_EL1_GPA (0xF << 24) /* QARMA generic code auth + algorithm */ +#define ID_AA64ISAR1_EL1_API (0xF << 8) /* Implementation-defined address + auth algorithm */ +#define ID_AA64ISAR1_EL1_APA (0xF << 4) /* QARMA address auth algorithm */ + /* * ID_AA64PFR0_EL1 bits definitions */ @@ -551,7 +590,6 @@ s32 psci_affinity_info(u32 function_id, u32 target_affinity, u32 psci_migrate_info_type(void); void psci_system_off(void); void psci_system_reset(void); -s32 psci_features(u32 function_id, u32 psci_fid); #endif #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index f60ee3a7e6a66aa339c5b91028f795eba27e6dbf..ea9bfe7570fdbb56f9e7ad15c7225ccc0581cb09 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -317,7 +317,6 @@ __weak void update_os_arch_secondary_cores(uint8_t os_arch) { } -#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 static void switch_to_el1(void) { if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && @@ -332,7 +331,6 @@ static void switch_to_el1(void) ES_TO_AARCH64); } #endif -#endif /* Subcommand: GO */ static void boot_jump_linux(bootm_headers_t *images, int flag) @@ -359,21 +357,33 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) update_os_arch_secondary_cores(images->os.arch); -#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 - armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, - (u64)switch_to_el1, ES_TO_AARCH64); +#ifdef CONFIG_ARMV8_MULTIENTRY + int armv8_switch_to_el1 = -1; #else - if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && - (images->os.arch == IH_ARCH_ARM)) - armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number, - (u64)images->ft_addr, 0, - (u64)images->ep, - ES_TO_AARCH32); - else - armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, - images->ep, - ES_TO_AARCH64); + int armv8_switch_to_el1 = env_get_yesno("armv8_switch_to_el1"); #endif +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + if (armv8_switch_to_el1 == -1) { + armv8_switch_to_el1 = 1; + } +#endif + if (armv8_switch_to_el1 == 1) { + armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, + (u64)switch_to_el1, ES_TO_AARCH64); + } else { + if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && + (images->os.arch == IH_ARCH_ARM)) + armv8_switch_to_el2(0, + (u64)gd->bd->bi_arch_number, + (u64)images->ft_addr, 0, + (u64)images->ep, + ES_TO_AARCH32); + else + armv8_switch_to_el2((u64)images->ft_addr, + 0, 0, 0, + images->ep, + ES_TO_AARCH64); + } } #else unsigned long machid = gd->bd->bi_arch_number; diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S index 46b6be21a8df8a3acd89568c319f8220b8f80428..956d258c9da476cd10545dac70a45cbe3df8407b 100644 --- a/arch/arm/lib/crt0.S +++ b/arch/arm/lib/crt0.S @@ -130,6 +130,14 @@ ENTRY(_main) ldr r9, [r9, #GD_NEW_GD] /* r9 <- gd->new_gd */ adr lr, here +#if defined(CONFIG_POSITION_INDEPENDENT) + adr r0, _main + ldr r1, _start_ofs + add r0, r1 + ldr r1, =CONFIG_SYS_TEXT_BASE + sub r1, r0 + add lr, r1 +#endif ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */ add lr, lr, r0 #if defined(CONFIG_CPU_V7M) @@ -180,3 +188,6 @@ here: #endif ENDPROC(_main) + +_start_ofs: + .word _start - _main diff --git a/arch/arm/lib/relocate.S b/arch/arm/lib/relocate.S index e5f7267be193e09db2db3e7b32ed7a1b93c2f09b..14b7f61c1a4bb4c5b222f1be0b1252f1ab4bdd85 100644 --- a/arch/arm/lib/relocate.S +++ b/arch/arm/lib/relocate.S @@ -78,22 +78,28 @@ ENDPROC(relocate_vectors) */ ENTRY(relocate_code) - ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */ - subs r4, r0, r1 /* r4 <- relocation offset */ - beq relocate_done /* skip relocation */ - ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */ - + adr r3, relocate_code + ldr r1, _image_copy_start_ofs + add r1, r3 /* r1 <- Run &__image_copy_start */ + subs r4, r0, r1 /* r4 <- Run to copy offset */ + beq relocate_done /* skip relocation */ + ldr r1, _image_copy_start_ofs + add r1, r3 /* r1 <- Run &__image_copy_start */ + ldr r2, _image_copy_end_ofs + add r2, r3 /* r2 <- Run &__image_copy_end */ copy_loop: - ldmia r1!, {r10-r11} /* copy from source address [r1] */ - stmia r0!, {r10-r11} /* copy to target address [r0] */ - cmp r1, r2 /* until source end address [r2] */ + ldmia r1!, {r10-r11} /* copy from source address [r1] */ + stmia r0!, {r10-r11} /* copy to target address [r0] */ + cmp r1, r2 /* until source end address [r2] */ blo copy_loop /* * fix .rel.dyn relocations */ - ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */ - ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */ + ldr r1, _rel_dyn_start_ofs + add r2, r1, r3 /* r2 <- Run &__rel_dyn_start */ + ldr r1, _rel_dyn_end_ofs + add r3, r1, r3 /* r3 <- Run &__rel_dyn_end */ fixloop: ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */ and r1, r1, #0xff @@ -129,3 +135,12 @@ relocate_done: #endif ENDPROC(relocate_code) + +_image_copy_start_ofs: + .word __image_copy_start - relocate_code +_image_copy_end_ofs: + .word __image_copy_end - relocate_code +_rel_dyn_start_ofs: + .word __rel_dyn_start - relocate_code +_rel_dyn_end_ofs: + .word __rel_dyn_end - relocate_code diff --git a/arch/arm/mach-snapdragon/misc.c b/arch/arm/mach-snapdragon/misc.c index 985625a548e78ed4916e544bc2b551503f32c5ef..7d452f4529b79c161e58af4eeafa7d2d651d65d5 100644 --- a/arch/arm/mach-snapdragon/misc.c +++ b/arch/arm/mach-snapdragon/misc.c @@ -9,6 +9,7 @@ #include #include #include +#include /* UNSTUFF_BITS macro taken from Linux Kernel: drivers/mmc/core/sd.c */ #define UNSTUFF_BITS(resp, start, size) \ @@ -33,21 +34,22 @@ u32 msm_board_serial(void) if (!mmc_dev) return 0; + if (mmc_init(mmc_dev)) + return 0; + return UNSTUFF_BITS(mmc_dev->cid, 16, 32); } void msm_generate_mac_addr(u8 *mac) { - int i; - char sn[9]; - - snprintf(sn, 9, "%08x", msm_board_serial()); - - /* fill in the mac with serialno, use locally adminstrated pool */ + /* use locally adminstrated pool */ mac[0] = 0x02; - mac[1] = 00; - for (i = 3; i >= 0; i--) { - mac[i + 2] = hextoul(&sn[2 * i], NULL); - sn[2 * i] = 0; - } + mac[1] = 0x00; + + /* + * Put the 32-bit serial number in the last 32-bit of the MAC address. + * Use big endian order so it is consistent with the serial number + * written as a hexadecimal string, e.g. 0x1234abcd -> 02:00:12:34:ab:cd + */ + put_unaligned_be32(msm_board_serial(), &mac[2]); } diff --git a/board/armltd/vexpress64/Kconfig b/board/armltd/vexpress64/Kconfig index 1d13f542e677ac9b59ec311d706a70a9c4cb0ffb..1f0c7ad9692b363dc59bc6b5a0f3385381b26ede 100644 --- a/board/armltd/vexpress64/Kconfig +++ b/board/armltd/vexpress64/Kconfig @@ -1,4 +1,5 @@ -if TARGET_VEXPRESS64_BASE_FVP || TARGET_VEXPRESS64_JUNO +if TARGET_VEXPRESS64_BASE_FVP || TARGET_VEXPRESS64_JUNO || \ + TARGET_VEXPRESS64_BASER_FVP config SYS_BOARD default "vexpress64" @@ -7,7 +8,7 @@ config SYS_VENDOR default "armltd" config SYS_CONFIG_NAME - default "vexpress_aemv8a" + default "vexpress_aemv8" config JUNO_DTB_PART string "NOR flash partition holding DTB" diff --git a/board/armltd/vexpress64/MAINTAINERS b/board/armltd/vexpress64/MAINTAINERS index 0ba044d7ff8711816df1ba8028de0df3aacc41bb..875401ae1b6781a6ca0221dd7622017b9e78e747 100644 --- a/board/armltd/vexpress64/MAINTAINERS +++ b/board/armltd/vexpress64/MAINTAINERS @@ -14,3 +14,8 @@ JUNO DEVELOPMENT PLATFORM BOARD M: Linus Walleij S: Maintained F: configs/vexpress_aemv8a_juno_defconfig + +VEXPRESS64 BASER_FVP +M: Peter Hoyes +S: Maintained +F: configs/vexpress_aemv8r_defconfig diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c index 2e4260286b5a89bf0024e886da3901ba5cb77259..eb4951d07c4c7e681ef4cb7bb468ad6f4db5b9b1 100644 --- a/board/armltd/vexpress64/vexpress64.c +++ b/board/armltd/vexpress64/vexpress64.c @@ -18,6 +18,7 @@ #include #include "pcie.h" #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -54,6 +55,27 @@ static struct mm_region vexpress64_mem_map[] = { struct mm_region *mem_map = vexpress64_mem_map; +static struct mpu_region vexpress64_aemv8r_mem_map[] = { + { + .start = 0x0UL, + .end = 0x7fffffffUL, + .attrs = PRLAR_ATTRIDX(MT_NORMAL) + }, { + .start = 0x80000000UL, + .end = 0xffffffffUL, + .attrs = PRLAR_ATTRIDX(MT_DEVICE_NGNRNE) + }, { + .start = 0x100000000UL, + .end = 0xffffffffffUL, + .attrs = PRLAR_ATTRIDX(MT_NORMAL) + }, { + /* List terminator */ + 0, + } +}; + +struct mpu_region *mpu_mem_map = vexpress64_aemv8r_mem_map; + /* This function gets replaced by platforms supporting PCIe. * The replacement function, eg. on Juno, initialises the PCIe bus. */ diff --git a/configs/sifive_unleashed_defconfig b/configs/sifive_unleashed_defconfig index cf501012815f46f132eed7cd92a1eb62e3c1cb6f..be947be9a0af693a570c0520588d73c1bf4dd9eb 100644 --- a/configs/sifive_unleashed_defconfig +++ b/configs/sifive_unleashed_defconfig @@ -24,7 +24,6 @@ CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_DM_SPI_FLASH=y CONFIG_SPL_DM_RESET=y CONFIG_SPL_SPI_LOAD=y -CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SPL_CLK=y diff --git a/configs/sifive_unmatched_defconfig b/configs/sifive_unmatched_defconfig index 890d3a01b0c6577fff0192f6e0931827c752014e..3d478ad3b93b5acb46edf9ee365de2dd574288a4 100644 --- a/configs/sifive_unmatched_defconfig +++ b/configs/sifive_unmatched_defconfig @@ -23,7 +23,6 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_ID_EEPROM=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_DM_RESET=y -CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_CMD_EEPROM=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_PWM=y diff --git a/configs/synquacer_developerbox_defconfig b/configs/synquacer_developerbox_defconfig index 802f1819e3c73b63f94941e9403dd15e4b7db856..a88856b272710a4db00ead61390a0a5f520d9e18 100644 --- a/configs/synquacer_developerbox_defconfig +++ b/configs/synquacer_developerbox_defconfig @@ -1,7 +1,6 @@ CONFIG_ARM=y -CONFIG_POSITION_INDEPENDENT=y CONFIG_ARCH_SYNQUACER=y -CONFIG_SYS_TEXT_BASE=0x00000000 +CONFIG_SYS_TEXT_BASE=0x08200000 CONFIG_ENV_SIZE=0x30000 CONFIG_ENV_OFFSET=0x300000 CONFIG_ENV_SECT_SIZE=0x10000 diff --git a/configs/vexpress_aemv8r_defconfig b/configs/vexpress_aemv8r_defconfig new file mode 100644 index 0000000000000000000000000000000000000000..bb4d1e5645fe9be5db85c9b16caeca127601eaee --- /dev/null +++ b/configs/vexpress_aemv8r_defconfig @@ -0,0 +1,19 @@ +CONFIG_ARM=y +CONFIG_TARGET_VEXPRESS64_BASER_FVP=y +CONFIG_SYS_TEXT_BASE=0x00001000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_SYS_MEMTEST_START=0x80000000 +CONFIG_SYS_MEMTEST_END=0xff000000 +CONFIG_ENV_SIZE=0x40000 +CONFIG_ENV_SECT_SIZE=0x40000 +CONFIG_IDENT_STRING=" vexpress_aemv8r64" +CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTDELAY=3 +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x9c090000 rootfstype=ext4 root=/dev/vda1 rw rootwait" +CONFIG_USE_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="fdt addr ${fdt_addr}; fdt resize; booti $kernel_addr - $fdt_addr" +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_SYS_PROMPT="VExpress64# " +CONFIG_OF_LIBFDT=y diff --git a/disk/part_iso.c b/disk/part_iso.c index 822f2c4d9f4084abf7e3424d8face1e55a353108..1061f341d3532dc2062b5a4d3568253849071a88 100644 --- a/disk/part_iso.c +++ b/disk/part_iso.c @@ -220,7 +220,7 @@ static void part_print_iso(struct blk_desc *dev_desc) printf("Part Start Sect x Size Type\n"); i=1; do { - printf(" %2d " LBAFU " " LBAFU " %6ld %.32s\n", + printf(" %2d %8" LBAFlength "u %8" LBAFlength "u %6ld %.32s\n", i, info.start, info.size, info.blksz, info.type); i++; } while (part_get_info_iso_verb(dev_desc, i, &info, 0) != -1); diff --git a/doc/README.semihosting b/doc/README.semihosting index c019999bedd8f0f394b98710d8fa35d7465abb0f..f382d0131eb341a40d6af341ce78cb470eb25c43 100644 --- a/doc/README.semihosting +++ b/doc/README.semihosting @@ -25,7 +25,7 @@ or turning on CONFIG_BASE_FVP for the more full featured model. Rather than create a new armv8 board similar to armltd/vexpress64, add semihosting calls to the existing one, enabled with CONFIG_SEMIHOSTING and CONFIG_BASE_FVP both set. Also reuse the existing board config file -vexpress_aemv8a.h but differentiate the two models by the presence or +vexpress_aemv8.h but differentiate the two models by the presence or absence of CONFIG_BASE_FVP. This change is tested and works on both the Foundation and Base fastmodel simulators. diff --git a/doc/arch/arm64.rst b/doc/arch/arm64.rst index 80498f6f6b8e4fe8e9b71ce73df2a9f54c4930b9..f20eb8f1b2893e5a2b21b10636e8e1ef7b4d7983 100644 --- a/doc/arch/arm64.rst +++ b/doc/arch/arm64.rst @@ -18,7 +18,8 @@ Notes classical firmware (like initial hardware setup, CPU errata workarounds or SMP bringup). U-Boot can be entered in EL2 when its main purpose is that of a boot loader. It can drop to lower exception levels before - entering the OS. + entering the OS. For ARMv8-R it is recommened to enter at S-EL2, as for this + architecture there is no S-EL3. 2. U-Boot for arm64 is compiled with AArch64-gcc. AArch64-gcc use rela relocation format, a tool(tools/relocate-rela) by Scott Wood diff --git a/doc/board/armltd/index.rst b/doc/board/armltd/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..b6786c114f17fa947bb8dc2d80d83c5176157a1b --- /dev/null +++ b/doc/board/armltd/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Arm Ltd +============= + +.. toctree:: + :maxdepth: 2 + + vexpress64.rst diff --git a/doc/board/armltd/vexpress64.rst b/doc/board/armltd/vexpress64.rst new file mode 100644 index 0000000000000000000000000000000000000000..37ef5641100ad48a5e62a482413bad2d4c49db9b --- /dev/null +++ b/doc/board/armltd/vexpress64.rst @@ -0,0 +1,57 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Arm Versatile Express +===================== + +The vexpress_* board configuration supports the following platforms: + + * FVP_Base_RevC-2xAEMvA + * FVP_BaseR_AEMv8R + * Juno development board + +Fixed Virtual Platforms +----------------------- + +The Fixed Virtual Platforms (FVP) are complete simulations of an Arm system, +including processor, memory and peripherals. They are set out in a "programmer's +view", which gives a comprehensive model on which to build and test software. + +The supported FVPs are available free of charge and can be downloaded from the +Arm developer site [1]_ (user registration might be required). + +Supported features: + + * GICv3 + * Generic timer + * PL011 UART + * SMC91111 network interface + +The default configuration assumes that U-Boot is boostrapped from the start of +the DRAM (address 0x80000000 for AEMvA; 0x00000000 for AEMv8R) using a suitable +bootloader. Alternatively, U-Boot can be launched directly by mapping the binary +to the same address (using the FVP's --data argument). + +The FVPs can be debugged using Arm Development Studio [2]_. + +FVP_BaseR +^^^^^^^^^ + +On Armv8r64 platforms (such as the FVP_BaseR), U-Boot runs at S-EL2, so +CONFIG_ARMV8_SWITCH_TO_EL1 is defined so that the next stage boots at S-EL1. If +S-EL2 is desired instead, the *armv8_switch_to_el1* environment variable is +available. This can be set to *n* to override the config flag and boot the next +stage at S-EL2 instead. + +Juno +---- + +The Juno development board is an open, vendor-neutral Armv8-A development +platform that supports an out-of-the-box Linux software package. A range of +plug-in expansion options enables hardware and software applications to be +developed and debugged. + +References +---------- + +.. [1] https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms +.. [2] https://developer.arm.com/tools-and-software/embedded/arm-development-studio diff --git a/doc/board/index.rst b/doc/board/index.rst index 8588e453d50c5adda49f782c2956f6e0aedb3d10..827f0866bd922ea1afdc742972dfcf11c5428bdb 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -10,6 +10,7 @@ Board-specific doc advantech/index AndesTech/index amlogic/index + armltd/index atmel/index congatec/index coreboot/index diff --git a/drivers/pci/pcie_iproc.c b/drivers/pci/pcie_iproc.c index 12ce9d525ca86e272dee50f08ae0b58610855596..be03dcbd97c01d61ed94ea57603585d727b65d1c 100644 --- a/drivers/pci/pcie_iproc.c +++ b/drivers/pci/pcie_iproc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2020 Broadcom + * Copyright (C) 2020-2021 Broadcom * */ @@ -12,6 +12,7 @@ #include #include #include +#include #include #define EP_PERST_SOURCE_SELECT_SHIFT 2 @@ -884,7 +885,7 @@ static int iproc_pcie_map_ranges(struct udevice *dev) for (i = 0; i < hose->region_count; i++) { if (hose->regions[i].flags == PCI_REGION_MEM || hose->regions[i].flags == PCI_REGION_PREFETCH) { - debug("%d: bus_addr %p, axi_addr %p, size 0x%lx\n", + debug("%d: bus_addr %p, axi_addr %p, size 0x%llx\n", i, &hose->regions[i].bus_start, &hose->regions[i].phys_start, hose->regions[i].size); @@ -1049,7 +1050,7 @@ static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie) while (!pci_get_dma_regions(pcie->dev, ®ions, i)) { dev_dbg(pcie->dev, - "dma %d: bus_addr %#lx, axi_addr %#llx, size %#lx\n", + "dma %d: bus_addr %#llx, axi_addr %#llx, size %#llx\n", i, regions.bus_start, regions.phys_start, regions.size); /* Each range entry corresponds to an inbound mapping region */ diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8.h similarity index 84% rename from include/configs/vexpress_aemv8a.h rename to include/configs/vexpress_aemv8.h index df22584d9abdb7dfb2ae9acfce5f7acb51d7c3d4..3447f020d3de52d8f4678d89865260736f9c2621 100644 --- a/include/configs/vexpress_aemv8a.h +++ b/include/configs/vexpress_aemv8.h @@ -10,30 +10,36 @@ #define CONFIG_REMAKE_ELF /* Link Definitions */ -#ifdef CONFIG_TARGET_VEXPRESS64_BASE_FVP +#ifdef CONFIG_TARGET_VEXPRESS64_JUNO +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x7fff0) +#else /* ATF loads u-boot here for BASE_FVP model */ #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x03f00000) -#elif CONFIG_TARGET_VEXPRESS64_JUNO -#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x7fff0) #endif #define CONFIG_SYS_BOOTM_LEN (64 << 20) /* Increase max gunzip size */ /* CS register bases for the original memory map. */ -#define V2M_PA_CS0 0x00000000 -#define V2M_PA_CS1 0x14000000 -#define V2M_PA_CS2 0x18000000 -#define V2M_PA_CS3 0x1c000000 -#define V2M_PA_CS4 0x0c000000 -#define V2M_PA_CS5 0x10000000 +#ifdef CONFIG_TARGET_VEXPRESS64_BASER_FVP +#define V2M_BASE 0x00000000 +#define V2M_PA_BASE 0x80000000 +#else +#define V2M_BASE 0x80000000 +#define V2M_PA_BASE 0x00000000 +#endif + +#define V2M_PA_CS0 (V2M_PA_BASE + 0x00000000) +#define V2M_PA_CS1 (V2M_PA_BASE + 0x14000000) +#define V2M_PA_CS2 (V2M_PA_BASE + 0x18000000) +#define V2M_PA_CS3 (V2M_PA_BASE + 0x1c000000) +#define V2M_PA_CS4 (V2M_PA_BASE + 0x0c000000) +#define V2M_PA_CS5 (V2M_PA_BASE + 0x10000000) #define V2M_PERIPH_OFFSET(x) (x << 16) #define V2M_SYSREGS (V2M_PA_CS3 + V2M_PERIPH_OFFSET(1)) #define V2M_SYSCTL (V2M_PA_CS3 + V2M_PERIPH_OFFSET(2)) #define V2M_SERIAL_BUS_PCI (V2M_PA_CS3 + V2M_PERIPH_OFFSET(3)) -#define V2M_BASE 0x80000000 - /* Common peripherals relative to CS7. */ #define V2M_AACI (V2M_PA_CS3 + V2M_PERIPH_OFFSET(4)) #define V2M_MMCI (V2M_PA_CS3 + V2M_PERIPH_OFFSET(5)) @@ -68,27 +74,27 @@ #define V2M_SYS_CFGSTAT (V2M_SYSREGS + 0x0a8) /* Generic Timer Definitions */ -#define COUNTER_FREQUENCY 24000000 /* 24MHz */ +#define COUNTER_FREQUENCY 100000000 /* 100MHz */ /* Generic Interrupt Controller Definitions */ #ifdef CONFIG_GICV3 -#define GICD_BASE (0x2f000000) -#define GICR_BASE (0x2f100000) +#define GICD_BASE (V2M_PA_BASE + 0x2f000000) +#define GICR_BASE (V2M_PA_BASE + 0x2f100000) #else -#ifdef CONFIG_TARGET_VEXPRESS64_BASE_FVP -#define GICD_BASE (0x2f000000) -#define GICC_BASE (0x2c000000) -#elif CONFIG_TARGET_VEXPRESS64_JUNO +#ifdef CONFIG_TARGET_VEXPRESS64_JUNO #define GICD_BASE (0x2C010000) #define GICC_BASE (0x2C02f000) +#else +#define GICD_BASE (V2M_PA_BASE + 0x2f000000) +#define GICC_BASE (V2M_PA_BASE + 0x2c000000) #endif #endif /* !CONFIG_GICV3 */ #ifndef CONFIG_TARGET_VEXPRESS64_JUNO /* The Vexpress64 simulators use SMSC91C111 */ #define CONFIG_SMC91111 1 -#define CONFIG_SMC91111_BASE (0x01A000000) +#define CONFIG_SMC91111_BASE (V2M_PA_BASE + 0x01A000000) #endif /* PL011 Serial Configuration */ @@ -113,7 +119,7 @@ #ifdef CONFIG_TARGET_VEXPRESS64_JUNO #define PHYS_SDRAM_2 (0x880000000) #define PHYS_SDRAM_2_SIZE 0x180000000 -#elif CONFIG_TARGET_VEXPRESS64_BASE_FVP && CONFIG_NR_DRAM_BANKS == 2 +#elif CONFIG_NR_DRAM_BANKS == 2 #define PHYS_SDRAM_2 (0x880000000) #define PHYS_SDRAM_2_SIZE 0x80000000 #endif @@ -200,6 +206,12 @@ " booti $kernel_addr - $fdt_addr; " \ "fi" #endif + +#elif CONFIG_TARGET_VEXPRESS64_BASER_FVP +#define CONFIG_EXTRA_ENV_SETTINGS \ + "kernel_addr=0x00800000\0" \ + "fdt_addr=0x03000000\0" \ + "boot_addr=0x0007f800\0" #endif /* Monitor Command Prompt */ @@ -213,7 +225,7 @@ /* Store environment at top of flash in the same location as blank.img */ /* in the Juno firmware. */ #else -#define CONFIG_SYS_FLASH_BASE 0x0C000000 +#define CONFIG_SYS_FLASH_BASE (V2M_PA_BASE + 0x0C000000) /* 256 x 256KiB sectors */ #define CONFIG_SYS_MAX_FLASH_SECT 256 /* Store environment at top of flash */ @@ -230,4 +242,8 @@ #define CONFIG_SYS_FLASH_EMPTY_INFO /* flinfo indicates empty blocks */ #define FLASH_MAX_SECTOR_SIZE 0x00040000 +#ifdef CONFIG_TARGET_VEXPRESS64_BASER_FVP +#define CONFIG_ARMV8_SWITCH_TO_EL1 +#endif + #endif /* __VEXPRESS_AEMV8A_H */ diff --git a/lib/Makefile b/lib/Makefile index 8ba745faa084a732959591fbf81d6aae84ca5b48..2d29cdad1ef1346e2ab1ab21b2120c1ed9835062 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -88,6 +88,7 @@ endif ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o obj-$(CONFIG_$(SPL_TPL_)HASH_SUPPORT) += crc16.o +obj-$(CONFIG_MMC_SPI_CRC_ON) += crc16.o obj-y += net_utils.o endif obj-$(CONFIG_ADDR_MAP) += addr_map.o diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index 2a61a5d6f04982708e9c814a10ee9d2774645c10..e39c39e23a175786b905e736b0f7cb97cd07b7ec 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -951,21 +951,23 @@ static int flash_read_buf(int dev, int fd, void *buf, size_t count, DEVNAME(dev), strerror(errno)); return -1; } - if (rc != readlen) { - fprintf(stderr, - "Read error on %s: Attempted to read %zd bytes but got %d\n", - DEVNAME(dev), readlen, rc); - return -1; - } #ifdef DEBUG fprintf(stderr, "Read 0x%x bytes at 0x%llx on %s\n", rc, (unsigned long long)blockstart + block_seek, DEVNAME(dev)); #endif - processed += readlen; - readlen = min(blocklen, count - processed); - block_seek = 0; - blockstart += blocklen; + processed += rc; + if (rc != readlen) { + fprintf(stderr, + "Warning on %s: Attempted to read %zd bytes but got %d\n", + DEVNAME(dev), readlen, rc); + readlen -= rc; + block_seek += rc; + } else { + blockstart += blocklen; + readlen = min(blocklen, count - processed); + block_seek = 0; + } } return processed;