mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-02 09:46:37 +03:00
When fpga load is called with a misaligned buffer address, the
versal_align_dma_buffer() function shifts the pointer forward to the
next aligned boundary and uses memcpy() to copy the data. Since the
destination is ahead of the source and the regions overlap, memcpy()
produces undefined behavior; in practice U-Boot's generic memcpy()
copies forward, repeating the first ARCH_DMA_MINALIGN-aligned chunk
throughout the buffer.
Replace memcpy() with memmove() which correctly handles overlapping
regions by copying backwards when the destination is ahead of the
source.
Fixes: 26e054c943 ("arm64: versal: fpga: Add PL bit stream load support")
Signed-off-by: Pranav Tilak <pranav.vinaytilak@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260507113359.3665220-1-pranav.vinaytilak@amd.com
60 lines
1.3 KiB
C
60 lines
1.3 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* (C) Copyright 2019, Xilinx, Inc,
|
|
* Siva Durga Prasad Paladugu <siva.durga.prasad.paladugu@amd.com>>
|
|
*/
|
|
|
|
#include <cpu_func.h>
|
|
#include <log.h>
|
|
#include <memalign.h>
|
|
#include <versalpl.h>
|
|
#include <zynqmp_firmware.h>
|
|
#include <asm/cache.h>
|
|
|
|
static ulong versal_align_dma_buffer(ulong *buf, u32 len)
|
|
{
|
|
ulong *new_buf;
|
|
|
|
if ((ulong)buf != ALIGN((ulong)buf, ARCH_DMA_MINALIGN)) {
|
|
new_buf = (ulong *)ALIGN((ulong)buf, ARCH_DMA_MINALIGN);
|
|
memmove(new_buf, buf, len);
|
|
buf = new_buf;
|
|
}
|
|
|
|
return (ulong)buf;
|
|
}
|
|
|
|
static int versal_load(xilinx_desc *desc, const void *buf, size_t bsize,
|
|
bitstream_type bstype, int flags)
|
|
{
|
|
ulong bin_buf;
|
|
int ret;
|
|
u32 buf_lo, buf_hi;
|
|
u32 ret_payload[PAYLOAD_ARG_CNT];
|
|
|
|
bin_buf = versal_align_dma_buffer((ulong *)buf, bsize);
|
|
|
|
debug("%s called!\n", __func__);
|
|
flush_dcache_range(bin_buf, bin_buf + bsize);
|
|
|
|
buf_lo = lower_32_bits(bin_buf);
|
|
buf_hi = upper_32_bits(bin_buf);
|
|
|
|
if (desc->family == xilinx_versal2) {
|
|
ret = xilinx_pm_request(VERSAL_PM_LOAD_PDI, VERSAL_PM_PDI_TYPE, buf_hi,
|
|
buf_lo, 0, 0, 0, ret_payload);
|
|
} else {
|
|
ret = xilinx_pm_request(VERSAL_PM_LOAD_PDI, VERSAL_PM_PDI_TYPE, buf_lo,
|
|
buf_hi, 0, 0, 0, ret_payload);
|
|
}
|
|
|
|
if (ret)
|
|
printf("PL FPGA LOAD failed with err: 0x%08x\n", ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
struct xilinx_fpga_op versal_op = {
|
|
.load = versal_load,
|
|
};
|