static void lb_dump_memory_ranges(struct lb_memory *mem) { int entries; int i; entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); printk(BIOS_DEBUG, "coreboot memory table:\n"); for(i = 0; i < entries; i++) { uint64_t entry_start = unpack_lb64(mem->map[i].start); uint64_t entry_size = unpack_lb64(mem->map[i].size); const char *entry_type; switch (mem->map[i].type) { case LB_MEM_RAM: entry_type="RAM"; break; case LB_MEM_RESERVED: entry_type="RESERVED"; break; case LB_MEM_ACPI: entry_type="ACPI"; break; case LB_MEM_NVS: entry_type="NVS"; break; case LB_MEM_UNUSABLE: entry_type="UNUSABLE"; break; case LB_MEM_VENDOR_RSVD: entry_type="VENDOR RESERVED"; break; case LB_MEM_TABLE: entry_type="CONFIGURATION TABLES"; break; default: entry_type="UNKNOWN!"; break; } printk(BIOS_DEBUG, "%2d. %016llx-%016llx: %s\n", i, entry_start, entry_start+entry_size-1, entry_type); } }
static void lb_reserve_table_memory(struct lb_header *head) { /* Dynamic cbmem has already reserved the memory where the coreboot tables * reside. Therefore, there is nothing to fix up. */ #if !CONFIG_DYNAMIC_CBMEM struct lb_record *last_rec; struct lb_memory *mem; uint64_t start; uint64_t end; int i, entries; last_rec = lb_last_record(head); mem = get_lb_mem(); start = (unsigned long)head; end = (unsigned long)last_rec; entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); /* Resize the right two memory areas so this table is in * a reserved area of memory. Everything has been carefully * setup so that is all we need to do. */ for(i = 0; i < entries; i++ ) { uint64_t map_start = unpack_lb64(mem->map[i].start); uint64_t map_end = map_start + unpack_lb64(mem->map[i].size); /* Does this area need to be expanded? */ if (map_end == start) { mem->map[i].size = pack_lb64(end - map_start); } /* Does this area need to be contracted? */ else if (map_start == start) { mem->map[i].start = pack_lb64(end); mem->map[i].size = pack_lb64(map_end - end); } } #endif }
/**************************************************************************** * memory_print_fn * * Display function for 'memory' item of coreboot table. ****************************************************************************/ static void memory_print_fn(const struct lb_record *rec) { char start_str[19], end_str[19], size_str[19]; const struct lb_memory *p; const char *mem_type; const struct lb_memory_range *ranges; uint64_t size, start, end; int i, entries; p = (const struct lb_memory *)rec; entries = (p->size - sizeof(*p)) / sizeof(p->map[0]); ranges = p->map; if (entries == 0) { printf("No memory ranges were found.\n"); return; } for (i = 0;;) { switch (ranges[i].type) { case LB_MEM_RAM: mem_type = "AVAILABLE"; break; case LB_MEM_RESERVED: mem_type = "RESERVED"; break; case LB_MEM_TABLE: mem_type = "CONFIG_TABLE"; break; default: mem_type = "UNKNOWN"; break; } size = unpack_lb64(ranges[i].size); start = unpack_lb64(ranges[i].start); end = start + size - 1; uint64_to_hex_string(start_str, start); uint64_to_hex_string(end_str, end); uint64_to_hex_string(size_str, size); printf("%s memory:\n" " from physical addresses %s to %s\n" " size is %s bytes (%lld in decimal)\n", mem_type, start_str, end_str, size_str, (unsigned long long)size); if (++i >= entries) break; printf("\n"); } }
/**************************************************************************** * memory_print_fn * * Display function for 'memory' item of coreboot table. ****************************************************************************/ static void memory_print_fn(const struct lb_record *rec) { const struct lb_memory *p; const char *mem_type; const struct lb_memory_range *ranges; uint64_t size, start, end; int i, entries; p = (const struct lb_memory *)rec; entries = (p->size - sizeof(*p)) / sizeof(p->map[0]); ranges = p->map; if (entries == 0) { printf("No memory ranges were found.\n"); return; } for (i = 0;;) { switch (ranges[i].type) { case LB_MEM_RAM: mem_type = "AVAILABLE"; break; case LB_MEM_RESERVED: mem_type = "RESERVED"; break; case LB_MEM_TABLE: mem_type = "CONFIG_TABLE"; break; default: mem_type = "UNKNOWN"; break; } size = unpack_lb64(ranges[i].size); start = unpack_lb64(ranges[i].start); end = start + size - 1; printf("%s memory:\n" " from physical addresses 0x%016" PRIx64 " to 0x%016" PRIx64 "\n size is 0x%016" PRIx64 " bytes (%" PRId64 " in decimal)\n", mem_type, start, end, size, size); if (++i >= entries) break; printf("\n"); } }
static void lb_remove_memory_range(struct lb_memory *mem, uint64_t start, uint64_t size) { uint64_t end; int entries; int i; end = start + size; entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); /* Remove a reserved area from the memory map */ for(i = 0; i < entries; i++) { uint64_t map_start = unpack_lb64(mem->map[i].start); uint64_t map_end = map_start + unpack_lb64(mem->map[i].size); if ((start <= map_start) && (end >= map_end)) { /* Remove the completely covered range */ memmove(&mem->map[i], &mem->map[i + 1], ((entries - i - 1) * sizeof(mem->map[0]))); mem->size -= sizeof(mem->map[0]); entries -= 1; /* Since the index will disappear revisit what will appear here */ i -= 1; } else if ((start > map_start) && (end < map_end)) { /* Split the memory range */ memmove(&mem->map[i + 1], &mem->map[i], ((entries - i) * sizeof(mem->map[0]))); mem->size += sizeof(mem->map[0]); entries += 1; /* Update the first map entry */ mem->map[i].size = pack_lb64(start - map_start); /* Update the second map entry */ mem->map[i + 1].start = pack_lb64(end); mem->map[i + 1].size = pack_lb64(map_end - end); /* Don't bother with this map entry again */ i += 1; } else if ((start <= map_start) && (end > map_start)) { /* Shrink the start of the memory range */ mem->map[i].start = pack_lb64(end); mem->map[i].size = pack_lb64(map_end - end); } else if ((start < map_end) && (start > map_start)) { /* Shrink the end of the memory range */ mem->map[i].size = pack_lb64(start - map_start); } } }
static void lb_cleanup_memory_ranges(struct lb_memory *mem) { int entries; int i, j; entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); /* Sort the lb memory ranges */ for(i = 0; i < entries; i++) { uint64_t entry_start = unpack_lb64(mem->map[i].start); for(j = i + 1; j < entries; j++) { uint64_t temp_start = unpack_lb64(mem->map[j].start); if (temp_start < entry_start) { struct lb_memory_range tmp; tmp = mem->map[i]; mem->map[i] = mem->map[j]; mem->map[j] = tmp; } } } /* Merge adjacent entries */ for(i = 0; (i + 1) < entries; i++) { uint64_t start, end, nstart, nend; if (mem->map[i].type != mem->map[i + 1].type) { continue; } start = unpack_lb64(mem->map[i].start); end = start + unpack_lb64(mem->map[i].size); nstart = unpack_lb64(mem->map[i + 1].start); nend = nstart + unpack_lb64(mem->map[i + 1].size); if ((start <= nstart) && (end >= nstart)) { if (start > nstart) { start = nstart; } if (end < nend) { end = nend; } /* Record the new region size */ mem->map[i].start = pack_lb64(start); mem->map[i].size = pack_lb64(end - start); /* Delete the entry I have merged with */ memmove(&mem->map[i + 1], &mem->map[i + 2], ((entries - i - 2) * sizeof(mem->map[0]))); mem->size -= sizeof(mem->map[0]); entries -= 1; /* See if I can merge with the next entry as well */ i -= 1; } } }