@@ -899,7 +899,7 @@ static void z7_dcache_clean_range(uintptr_t start, uint32_t len)
899899int hal_fpga_load (uint32_t flags , uintptr_t addr , size_t size )
900900{
901901 uint32_t sts ;
902- uint32_t words = ( uint32_t )(( size + 3U ) / 4U ) ;
902+ uint32_t words ;
903903 uint64_t t0 ;
904904
905905 if (flags == HAL_FPGA_PARTIAL ) {
@@ -911,14 +911,31 @@ int hal_fpga_load(uint32_t flags, uintptr_t addr, size_t size)
911911 if (addr > 0xFFFFFFFFU || size == 0 ) {
912912 return -1 ;
913913 }
914+ #if defined(SIZE_MAX ) && SIZE_MAX > 0xFFFFFFFFU
915+ /* words and the DMA length register are 32-bit; reject a size that would
916+ * truncate. Compiled out where size_t is already 32-bit. */
917+ if (size > 0xFFFFFFFFU ) {
918+ wolfBoot_printf ("Z7 FPGA: bitstream size too large\n" );
919+ return -1 ;
920+ }
921+ #endif
914922 /* The DevC DMA descriptor encodes the "last" flag in the source
915923 * address LSB, so the bitstream buffer must be word-aligned. */
916924 if ((addr & 0x3U ) != 0U ) {
917925 wolfBoot_printf ("Z7 FPGA: bitstream addr not word-aligned\n" );
918926 return -1 ;
919927 }
920928
921- /* 1. Unlock DevC and select PCAP (not ICAP). */
929+ /* Round byte size up to whole words without overflowing size + 3. */
930+ words = (uint32_t )(size / 4U );
931+ if ((size & 3U ) != 0U ) {
932+ words ++ ;
933+ }
934+
935+ /* 1. Unlock DevC and select PCAP (not ICAP). PCAP_MODE=1 enables the
936+ * PCAP interface; PCAP_PR=1 selects PCAP (0 would select ICAP) per
937+ * UG585 devcfg.CTRL bit 27. This matches Xilinx FSBL pcap.c, which
938+ * sets both bits for full-bitstream programming. */
922939 Z7_DEVC_UNLOCK = Z7_DEVC_UNLOCK_KEY ;
923940 Z7_DEVC_CTRL |= (Z7_DEVC_CTRL_PCAP_MODE | Z7_DEVC_CTRL_PCAP_PR );
924941 /* Disable internal PCAP loopback. */
@@ -954,7 +971,18 @@ int hal_fpga_load(uint32_t flags, uintptr_t addr, size_t size)
954971 * bitstreams are word streams, so this normally equals size.) */
955972 z7_dcache_clean_range (addr , words * 4U );
956973
957- /* 6. Program the DMA: src = DDR bitstream (LSB=1 marks last descriptor),
974+ /* 6. Wait for room in the DevC DMA command queue, then program the DMA.
975+ * Writing a descriptor while the queue is full silently drops it,
976+ * leaving step 7 to spin to the timeout. */
977+ t0 = hal_get_timer_us ();
978+ while (Z7_DEVC_STATUS & Z7_DEVC_STATUS_DMA_CMD_FULL ) {
979+ if (hal_get_timer_us () - t0 > Z7_FPGA_TIMEOUT_US ) {
980+ wolfBoot_printf ("Z7 FPGA: timeout waiting DMA queue space\n" );
981+ return -1 ;
982+ }
983+ }
984+
985+ /* src = DDR bitstream (LSB=1 marks last descriptor),
958986 * dst = PCAP sentinel. Lengths are in 32-bit words. */
959987 Z7_DEVC_DMA_SRC = ((uint32_t )addr ) | Z7_DEVC_DMA_LAST ;
960988 Z7_DEVC_DMA_DST = Z7_DEVC_DMA_DEST_PCAP ;
0 commit comments