/* Copyright (c) 2009,13 The Regents of the University of California
 * Barret Rhoden <brho@cs.berkeley.edu>
 * Kevin Klues <klueska@cs.berkeley.edu>
 * See LICENSE for details.
 *
 * Multiboot parsing and helper functions. */

#include <multiboot.h>
#include <ros/common.h>
#include <arch/mmu.h>
#include <arch/arch.h>
#include <ros/memlayout.h>
#include <stdio.h>
#include <pmap.h>

#ifdef CONFIG_X86
#include <arch/apic.h>
#endif

/* Misc dead code to read from mboot.  We'll need to do this to run a legit
 * initrd from grub (module /initramfs.cpio, or whatever). */
static void mboot_parsing(struct multiboot_info *mbi)
{
	if (mbi->flags & MULTIBOOT_INFO_BOOTDEV)
		printk("MBI: boot_device = 0x%08x\n", mbi->boot_device);
	if (mbi->flags & MULTIBOOT_INFO_CMDLINE)
		printk("MBI: command line: %s\n",
		       (char*)((physaddr_t)mbi->cmdline + KERNBASE));
	if (mbi->flags & MULTIBOOT_INFO_MODS) {
		printk("MBI: nr mods, %d: mods addr %p\n", mbi->mods_count,
		       mbi->mods_addr);
	}
}

bool mboot_has_mmaps(struct multiboot_info *mbi)
{
	return mbi->flags & MULTIBOOT_INFO_MEM_MAP;
}

/* This only notices bios detectable memory - there's a lot more in the higher
 * paddrs. */
void mboot_detect_memory(struct multiboot_info *mbi)
{
	physaddr_t max_bios_mem;
	physaddr_t max_bios_addr;
	size_t basemem;
	size_t extmem;
	if (!(mbi->flags & MULTIBOOT_INFO_MEMORY)) {
		printk("No BIOS memory info from multiboot, crash impending!\n");
		return;
	}
	/* mem_lower and upper are measured in KB.  They are 32 bit values, so we're
	 * limited to 4TB total. */
	basemem = ROUNDDOWN((size_t)mbi->mem_lower * 1024, PGSIZE);
	/* On 32 bit, This shift << 10 could cause us to lose some memory, but we
	 * weren't going to access it anyways (won't go beyond ~1GB) */
	extmem = ROUNDDOWN((size_t)mbi->mem_upper * 1024, PGSIZE);
	/* Calculate the maximum physical address based on whether or not there is
	 * any extended memory. */
	if (extmem) {
		max_bios_mem = EXTPHYSMEM + extmem;
		/* On 32 bit, if we had enough RAM that adding a little wrapped us
		 * around, we'll back off a little and run with just extmem amount (in
		 * essence, subtracing 1MB). */
		if (max_bios_mem < extmem)
			max_bios_mem = extmem;
	} else {
		max_bios_mem = basemem;
	}
	max_bios_addr = MIN(max_bios_mem, KERN_VMAP_TOP - KERNBASE);
	printk("Base memory: %luK, Extended memory: %luK\n", basemem / 1024,
	       extmem / 1024);
	printk("Maximum directly addressable base and extended memory: %luK\n",
	       max_bios_addr / 1024);
	/* Take a first stab at the max pmem, in case there are no memory mappings
	 * (like in riscv) */
	max_pmem = max_bios_mem;
}

void mboot_foreach_mmap(struct multiboot_info *mbi, mboot_foreach_t func,
                        void *data)
{
	struct multiboot_mmap_entry *mmap_b, *mmap_e, *mmap_i;
	if (!mboot_has_mmaps(mbi)) {
		printd("No memory mapping info from multiboot\n");
		return;
	}
	mmap_b = (struct multiboot_mmap_entry*)((size_t)mbi->mmap_addr + KERNBASE);
	mmap_e = (struct multiboot_mmap_entry*)((size_t)mbi->mmap_addr + KERNBASE
	                                   + mbi->mmap_length);
	printd("mmap_addr = %p, mmap_length = %p\n", mbi->mmap_addr,
	       mbi->mmap_length);
	/* Note when we incremement mmap_i, we add in the value of size... */
	for (mmap_i = mmap_b;
	     mmap_i < mmap_e;
	     mmap_i = (struct multiboot_mmap_entry*)((void*)mmap_i + mmap_i->size
	                                             + sizeof(mmap_i->size))) {
		func(mmap_i, data);
	}
}

void mboot_print_mmap(struct multiboot_info *mbi)
{
	void print_entry(struct multiboot_mmap_entry *entry, void *data)
	{
		printk("Base = 0x%016llx, Length = 0x%016llx : %s\n",
		       entry->addr, entry->len,
		       entry->type == MULTIBOOT_MEMORY_AVAILABLE ? "FREE" :
		                                                   "RESERVED");
	}
	mboot_foreach_mmap(mbi, print_entry, 0);
}

/* Given a range of memory, will tell us if multiboot is using anything we care
 * about in that range.  It usually uses memory below 1MB, so boot_alloc is
 * fine.  This is pre, so MBI is still a paddr. */
bool mboot_region_collides(struct multiboot_info *mbi, uintptr_t base,
                           uintptr_t end)
{
	if (regions_collide_unsafe((uintptr_t)mbi,
	                           (uintptr_t)mbi + sizeof(struct multiboot_info),
	                           base, end))
		return TRUE;
	if (mboot_has_mmaps(mbi)) {
		if (regions_collide_unsafe((uintptr_t)mbi->mmap_addr + KERNBASE,
		                           (uintptr_t)mbi->mmap_addr + KERNBASE
		                                                     + mbi->mmap_length,
		                           base, end))
			return TRUE;
	}
	return FALSE;
}
