100100static int pci_enum_is_64bit (uint32_t value );
101101static int pci_enum_is_mmio (uint32_t value );
102102
103- static inline uint32_t align_up (uint32_t address , uint32_t alignment ) {
104- return (address + alignment - 1 ) & ~(alignment - 1 );
103+ static inline uint64_t align_up (uint64_t address , uint32_t alignment ) {
104+ return (address + alignment - 1 ) & ~(uint64_t )( alignment - 1 );
105105}
106106
107107static inline uint32_t align_down (uint32_t address , uint32_t alignment ) {
108108 return address & ~(alignment - 1 );
109109}
110110
111- static int pci_align_check_up (uint32_t address , uint32_t alignment ,
112- uint32_t limit , uint32_t * aligned )
111+ static int pci_align_check_up (uint64_t address , uint32_t alignment ,
112+ uint64_t limit , uint64_t * aligned )
113113{
114- uint32_t a ;
114+ uint64_t a ;
115115 a = align_up (address , alignment );
116116 if (a < address || a >= limit )
117117 return -1 ;
@@ -363,17 +363,20 @@ static int pci_enum_is_mmio(uint32_t value)
363363 return (value & PCI_ENUM_MMIND_MASK ) == 0 ;
364364}
365365
366- static int pci_enum_next_aligned32 (uint32_t address , uint32_t * next ,
367- uint32_t align , uint32_t limit )
366+ static int pci_enum_next_aligned32 (uint64_t address , uint32_t * next ,
367+ uint32_t align , uint64_t limit )
368368{
369- uintptr_t addr ;
369+ uint64_t addr ;
370370
371- addr = (uintptr_t )address ;
371+ /* 64-bit on purpose: an exhausted pool leaves the cursor at
372+ * 0x100000000, which a 32-bit type (uintptr_t included on 32-bit
373+ * targets) would truncate back to 0. */
374+ addr = address ;
372375 align = align - 1 ;
373- addr = (addr + align ) & (~align );
376+ addr = (addr + align ) & (~( uint64_t ) align );
374377 if (addr > 0xffffffff )
375378 return -1 ;
376- if (addr < ( uintptr_t ) address )
379+ if (addr < address )
377380 return -1 ;
378381 if (addr >= limit )
379382 return -1 ;
@@ -421,8 +424,8 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
421424 uint32_t length , align ;
422425 uint8_t bar_off ;
423426 int is_prefetch ;
424- uint32_t * base ;
425- uint32_t limit ;
427+ uint64_t * base ;
428+ uint64_t limit ;
426429 uint32_t reg ;
427430 int is_mmio ;
428431 int ret = 0 ;
@@ -524,7 +527,7 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
524527 pci_config_write32 (bus , dev , fun , bar_off , bar_value );
525528 if (* is_64bit )
526529 pci_config_write32 (bus , dev , fun , bar_off + 4 , 0x0 );
527- * base = bar_value + length ;
530+ * base = ( uint64_t ) bar_value + length ;
528531 PCI_DEBUG_PRINTF ("PCI enum: %s bus: %x:%x.%x bar: %d [%x,%x] (0x%x %s %s)\r\n" ,
529532 (is_mmio ? "mm" : "io" ), bus , dev , fun , bar_idx , bar_value ,
530533 bar_value + length , length , (* is_64bit ) ? "64bit" : "" ,
@@ -617,14 +620,14 @@ static inline void pci_dump_bridge(uint8_t bus, uint8_t dev, uint8_t fun)
617620static int pci_program_bridge (uint8_t bus , uint8_t dev , uint8_t fun ,
618621 struct pci_enum_info * info )
619622{
620- uint32_t prefetch_start ;
621- uint32_t mem_start ;
622- uint32_t io_start ;
623+ uint64_t prefetch_start ;
624+ uint64_t mem_start ;
625+ uint64_t io_start ;
623626 uint32_t orig_cmd ;
624627 uint8_t saved_bus ;
625- uint32_t saved_mem ;
626- uint32_t saved_pf ;
627- uint32_t saved_io ;
628+ uint64_t saved_mem ;
629+ uint64_t saved_pf ;
630+ uint64_t saved_io ;
628631 int ret ;
629632
630633 saved_bus = info -> curr_bus_number ;
@@ -635,6 +638,13 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
635638 orig_cmd = pci_config_read16 (bus , dev , fun , PCI_COMMAND_OFFSET );
636639 pci_config_write16 (bus , dev , fun , PCI_COMMAND_OFFSET , 0 );
637640
641+ /* curr_bus_number is one bus per bridge level; at 0xFF the next
642+ * increment wraps to 0, which would write SECONDARY_BUS 0 and
643+ * re-enumerate bus 0 over the already configured tree. Disable
644+ * this bridge instead. */
645+ if (info -> curr_bus_number == 0xFF )
646+ goto err ;
647+
638648 info -> curr_bus_number ++ ;
639649 PCI_DEBUG_PRINTF ("Bridge: %x.%x.%x (using bus number: %d)\r\n" ,
640650 (int )bus , (int )dev , (int )fun , info -> curr_bus_number );
@@ -926,11 +936,28 @@ int pci_enum_do(void)
926936 struct pci_enum_info enum_info ;
927937 int ret ;
928938
939+ /* Pool limits are exclusive ends: the allocator accepts a region
940+ * when its end is <= limit (pci_enum_next_aligned32, the BAR end
941+ * check, pci_align_check_up) and the IO limit is the 16-bit IO
942+ * ceiling, not the last usable address. A region ending exactly
943+ * at base + length must fit, so initialize base + length. The
944+ * limit fields are 64-bit because a pool may end exactly at
945+ * 0x100000000 (4 GiB), the top of the 32-bit space; reject only
946+ * pools whose end is above it. */
947+ if ((uint64_t )PCI_MMIO32_BASE + PCI_MMIO32_LENGTH > 0x100000000ULL ||
948+ (uint64_t )PCI_MMIO32_PREFETCH_BASE +
949+ PCI_MMIO32_PREFETCH_LENGTH > 0x100000000ULL )
950+ {
951+ PCI_DEBUG_PRINTF ("PCI MMIO pool overflows the 32-bit address "
952+ "space\r\n" );
953+ return -1 ;
954+ }
955+
929956 enum_info .mem = PCI_MMIO32_BASE ;
930- enum_info .mem_limit = enum_info .mem + ( PCI_MMIO32_LENGTH - 1 ) ;
957+ enum_info .mem_limit = ( uint64_t ) enum_info .mem + PCI_MMIO32_LENGTH ;
931958 enum_info .mem_pf = PCI_MMIO32_PREFETCH_BASE ;
932- enum_info .mem_pf_limit = enum_info .mem_pf +
933- ( PCI_MMIO32_PREFETCH_LENGTH - 1 ) ;
959+ enum_info .mem_pf_limit = ( uint64_t ) enum_info .mem_pf +
960+ PCI_MMIO32_PREFETCH_LENGTH ;
934961 enum_info .io = PCI_IO32_BASE ;
935962 enum_info .curr_bus_number = 0 ;
936963
@@ -943,16 +970,17 @@ int pci_enum_do(void)
943970 ret = pci_enum_bus (0 , & enum_info );
944971
945972 PCI_DEBUG_PRINTF ("PCI Memory Mapped I/O range [0x%x,0x%x] (0x%x)\r\n" ,
946- (uint32_t )PCI_MMIO32_BASE , enum_info .mem ,
947- enum_info .mem - PCI_MMIO32_BASE );
973+ (uint32_t )PCI_MMIO32_BASE , ( uint32_t ) enum_info .mem ,
974+ ( uint32_t )( enum_info .mem - PCI_MMIO32_BASE ) );
948975
949976 PCI_DEBUG_PRINTF ("PCI Memory Mapped I/O range (prefetch) [0x%x,0x%x] (0x%x)\r\n" ,
950- (uint32_t )PCI_MMIO32_PREFETCH_BASE , enum_info .mem_pf ,
951- enum_info .mem_pf - PCI_MMIO32_PREFETCH_BASE );
977+ (uint32_t )PCI_MMIO32_PREFETCH_BASE ,
978+ (uint32_t )enum_info .mem_pf ,
979+ (uint32_t )(enum_info .mem_pf - PCI_MMIO32_PREFETCH_BASE ));
952980
953981 PCI_DEBUG_PRINTF ("PCI I/O range [0x%x,0x%x] (0x%x)\r\n" ,
954- (uint32_t )PCI_IO32_BASE , enum_info .io ,
955- enum_info .io - PCI_IO32_BASE );
982+ (uint32_t )PCI_IO32_BASE , ( uint32_t ) enum_info .io ,
983+ ( uint32_t )( enum_info .io - PCI_IO32_BASE ) );
956984
957985 return ret ;
958986}
0 commit comments