| 179 | |
| 180 | private: |
| 181 | void load_chunks() { |
| 182 | u64 file_size = src_->size(); |
| 183 | u64 off = 0; |
| 184 | while (off + sizeof(AvmlChunkHeader) <= file_size) { |
| 185 | AvmlChunkHeader h{}; |
| 186 | if (src_->read(off, &h, sizeof(h)) != sizeof(h)) |
| 187 | throw_error("AVML: short read at {:#x}", off); |
| 188 | if (h.magic != kAvmlMagic) |
| 189 | throw_error("AVML: bad magic at chunk offset {:#x}", off); |
| 190 | if (h.version != 2) |
| 191 | throw_error("AVML: unsupported version {} at {:#x}", h.version, off); |
| 192 | if (h.end <= h.start) |
| 193 | throw_error("AVML: bad chunk range {:#x}-{:#x}", h.start, h.end); |
| 194 | |
| 195 | u64 chunk_decompressed_len = h.end - h.start; |
| 196 | u64 chunk_data_off = off + sizeof(AvmlChunkHeader); |
| 197 | u64 chunk_data_max = file_size - chunk_data_off; |
| 198 | u64 consumed = parse_snappy_frames( |
| 199 | chunk_data_off, chunk_data_max, chunk_decompressed_len, h.start); |
| 200 | off = chunk_data_off + consumed + 8; // skip 8-byte trailer |
| 201 | } |
| 202 | if (frames_.empty()) throw_error("AVML: no frames decoded"); |
| 203 | max_addr_ = frames_.back().pa_start + frames_.back().pa_length; |
| 204 | log::info("AVML: {} chunk-frames, max PA = {:#x}", frames_.size(), max_addr_); |
| 205 | } |
| 206 | |
| 207 | // Walks the framed-snappy stream starting at `file_off`, producing frames |
| 208 | // whose decompressed bytes map to physical addresses [chunk_pa_start, ...]. |
nothing calls this directly
no test coverage detected