/* 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;
}
