void cbmem_initialize_empty(void) { uintptr_t pointer_addr; uintptr_t root_addr; unsigned long max_entries; struct cbmem_root *root; struct cbmem_root_pointer *pointer; /* Place the root pointer and the root. The number of entries is * dictated by difference between the root address and the pointer * where the root address is aligned down to * DYN_CBMEM_ALIGN_SIZE. The pointer falls just below the * address returned by get_top_aligned(). */ pointer_addr = get_top_aligned(); if (pointer_addr == 0) return; root_addr = pointer_addr - ROOT_MIN_SIZE; root_addr &= ~(DYN_CBMEM_ALIGN_SIZE - 1); pointer_addr -= sizeof(struct cbmem_root_pointer); max_entries = (pointer_addr - (root_addr + sizeof(*root))) / sizeof(struct cbmem_entry); pointer = (void *)pointer_addr; pointer->magic = CBMEM_POINTER_MAGIC; pointer->root = root_addr; root = (void *)root_addr; root->max_entries = max_entries; root->num_entries = 0; root->locked = 0; root->size = pointer_addr - root_addr + sizeof(struct cbmem_root_pointer); /* Add an entry covering the root region. */ cbmem_entry_append(root, CBMEM_ID_ROOT, root_addr, root->size); printk(BIOS_DEBUG, "CBMEM: root @ %p %d entries.\n", root, root->max_entries); /* Complete migration to CBMEM. */ cbmem_run_init_hooks(); }
const struct cbmem_entry *cbmem_entry_add(u32 id, u64 size64) { struct cbmem_root *root; const struct cbmem_entry *entry; unsigned long base; u32 size; u32 aligned_size; entry = cbmem_entry_find(id); if (entry != NULL) return entry; /* Only handle sizes <= UINT_MAX internally. */ if (size64 > (u64)UINT_MAX) return NULL; size = size64; root = get_root(); if (root == NULL) return NULL; /* Nothing can be added once it is locked down. */ if (root->locked) return NULL; if (root->max_entries == root->num_entries) return NULL; aligned_size = ALIGN(size, DYN_CBMEM_ALIGN_SIZE); base = (unsigned long)cbmem_base(); base -= aligned_size; return cbmem_entry_append(root, id, base, aligned_size); }