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();
}
Beispiel #2
0
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);
}