Return < 0 on error, 0 on success. */
| 160 | |
| 161 | /* Return < 0 on error, 0 on success. */ |
| 162 | static int parse_cbtable(uint64_t address, size_t table_size) |
| 163 | { |
| 164 | const uint8_t *buf; |
| 165 | struct mapping header_mapping; |
| 166 | size_t req_size; |
| 167 | size_t i; |
| 168 | |
| 169 | req_size = table_size; |
| 170 | /* Default to 4 KiB search space. */ |
| 171 | if (req_size == 0) |
| 172 | req_size = 4 * 1024; |
| 173 | |
| 174 | debug("Looking for coreboot table at %" PRIx64 " %zd bytes.\n", address, req_size); |
| 175 | |
| 176 | buf = map_memory(&header_mapping, address, req_size); |
| 177 | |
| 178 | if (!buf) |
| 179 | return -1; |
| 180 | |
| 181 | /* look at every 16 bytes */ |
| 182 | for (i = 0; i <= req_size - sizeof(struct lb_header); i += 16) { |
| 183 | const struct lb_header *lbh; |
| 184 | struct mapping table_mapping; |
| 185 | |
| 186 | lbh = (const struct lb_header *)&buf[i]; |
| 187 | if (memcmp(lbh->signature, "LBIO", sizeof(lbh->signature)) || |
| 188 | !lbh->header_bytes || ipchksum(lbh, sizeof(*lbh))) { |
| 189 | continue; |
| 190 | } |
| 191 | |
| 192 | /* Map in the whole table to parse. */ |
| 193 | if (!map_memory(&table_mapping, address + i, |
| 194 | lbh->header_bytes + lbh->table_bytes)) { |
| 195 | debug("Couldn't map in table\n"); |
| 196 | continue; |
| 197 | } |
| 198 | |
| 199 | const uint8_t *table_contents = |
| 200 | &((uint8_t *)mapping_virt(&table_mapping))[lbh->header_bytes]; |
| 201 | if (ipchksum(table_contents, lbh->table_bytes) != |
| 202 | lbh->table_checksum) { |
| 203 | debug("Signature found, but wrong checksum.\n"); |
| 204 | unmap_memory(&table_mapping); |
| 205 | continue; |
| 206 | } |
| 207 | |
| 208 | debug("Found at %#" PRIx64 "\n", address + i); |
| 209 | |
| 210 | const struct lb_record *lbr_p; |
| 211 | |
| 212 | for (size_t offset = 0; offset < lbh->table_bytes; offset += lbr_p->size) { |
| 213 | lbr_p = (const struct lb_record *)&table_contents[offset]; |
| 214 | debug(" coreboot table entry 0x%02x\n", lbr_p->tag); |
| 215 | |
| 216 | if (lbr_p->tag != LB_TAG_FORWARD) |
| 217 | continue; |
| 218 | |
| 219 | /* This is a forwarding entry. Repeat the search at the new address. */ |
no test coverage detected