Ejemplo n.º 1
0
/*
 * zImage booting support
 */
static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
			char * const argv[], bootm_headers_t *images)
{
	int ret;
	void *zi_start, *zi_end;

	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
			      images, 1);

	/* Setup Linux kernel zImage entry point */
	if (argc < 2) {
		images->ep = load_addr;
		debug("*  kernel: default image load address = 0x%08lx\n",
				load_addr);
	} else {
		images->ep = simple_strtoul(argv[1], NULL, 16);
		debug("*  kernel: cmdline image address = 0x%08lx\n",
			images->ep);
	}

	ret = bootz_setup((void *)images->ep, &zi_start, &zi_end);
	if (ret != 0)
		return 1;

	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);

	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_FINDOTHER,
			      images, 1);

	return ret;
}
Ejemplo n.º 2
0
void arch_lmb_reserve(struct lmb *lmb)
{
	ulong sp;

	/*
	 * Booting a (Linux) kernel image
	 *
	 * Allocate space for command line and board info - the
	 * address should be as high as possible within the reach of
	 * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
	 * memory, which means far enough below the current stack
	 * pointer.
	 */
	sp = get_sp();
	debug("## Current stack ends at 0x%08lx ", sp);

	/* adjust sp by 1K to be safe */
	sp -= 1024;

	/*
	 * Skip reservation if our stack is not in external RAM
	 */
	if (sp >= gd->bd->bi_dram[0].start &&
	    sp <  gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size) {
		lmb_reserve(lmb, sp, gd->bd->bi_dram[0].start +
			    gd->bd->bi_dram[0].size - sp);
	}
}
Ejemplo n.º 3
0
/*
 * zImage booting support
 */
static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
			char * const argv[], bootm_headers_t *images)
{
	int ret;
	ulong zi_start, zi_end;

	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
			      images, 1);

	/* Setup Linux kernel zImage entry point */
	if (!argc) {
		images->ep = load_addr;
		debug("*  kernel: default image load address = 0x%08lx\n",
				load_addr);
	} else {
		images->ep = simple_strtoul(argv[0], NULL, 16);
		debug("*  kernel: cmdline image address = 0x%08lx\n",
			images->ep);
	}

	ret = bootz_setup(images->ep, &zi_start, &zi_end);
	if (ret != 0)
		return 1;

	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);

	/*
	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
	 * have a header that provide this informaiton.
	 */
	if (bootm_find_images(flag, argc, argv))
		return 1;

	return 0;
}
Ejemplo n.º 4
0
void __init reserve_crashkernel(void)
{
	unsigned long size;

	if (crashk_res.start == 0)
		return;

	/* We might have got these values via the command line or the
	 * device tree, either way sanitise them now. */

	size = crashk_res.end - crashk_res.start + 1;

	if (crashk_res.start != KDUMP_KERNELBASE)
		printk("Crash kernel location must be 0x%x\n",
				KDUMP_KERNELBASE);

	crashk_res.start = KDUMP_KERNELBASE;
	size = PAGE_ALIGN(size);
	crashk_res.end = crashk_res.start + size - 1;

	/* Crash kernel trumps memory limit */
	if (memory_limit && memory_limit <= crashk_res.end) {
		memory_limit = crashk_res.end + 1;
		printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
				memory_limit);
	}

	lmb_reserve(crashk_res.start, size);
}
Ejemplo n.º 5
0
static int bootm_load_os(bootm_headers_t *images, int boot_progress)
{
	image_info_t os = images->os;
	ulong load = os.load;
	ulong load_end;
	ulong blob_start = os.start;
	ulong blob_end = os.end;
	ulong image_start = os.image_start;
	ulong image_len = os.image_len;
	ulong flush_start = ALIGN_DOWN(load, ARCH_DMA_MINALIGN);
	ulong flush_len;
	bool no_overlap;
	void *load_buf, *image_buf;
	int err;

	load_buf = map_sysmem(load, 0);
	image_buf = map_sysmem(os.image_start, image_len);
	err = bootm_decomp_image(os.comp, load, os.image_start, os.type,
				 load_buf, image_buf, image_len,
				 CONFIG_SYS_BOOTM_LEN, &load_end);
	if (err) {
		bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
		return err;
	}

	flush_len = load_end - load;
	if (flush_start < load)
		flush_len += load - flush_start;

	flush_cache(flush_start, ALIGN(flush_len, ARCH_DMA_MINALIGN));

	debug("   kernel loaded at 0x%08lx, end = 0x%08lx\n", load, load_end);
	bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED);

	no_overlap = (os.comp == IH_COMP_NONE && load == image_start);

	if (!no_overlap && load < blob_end && load_end > blob_start) {
		debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n",
		      blob_start, blob_end);
		debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load,
		      load_end);

		/* Check what type of image this is. */
		if (images->legacy_hdr_valid) {
			if (image_get_type(&images->legacy_hdr_os_copy)
					== IH_TYPE_MULTI)
				puts("WARNING: legacy format multi component image overwritten\n");
			return BOOTM_ERR_OVERLAP;
		} else {
			puts("ERROR: new format image overwritten - must RESET the board to recover\n");
			bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
			return BOOTM_ERR_RESET;
		}
	}

	lmb_reserve(&images->lmb, images->os.load, (load_end -
						    images->os.load));
	return 0;
}
Ejemplo n.º 6
0
void cpu_mp_lmb_reserve(struct lmb *lmb)
{
	u32 bootpg;

	/* if we have 4G or more of memory, put the boot page at 4Gb-4k */
	if ((u64)gd->ram_size > 0xfffff000)
		bootpg = 0xfffff000;
	else
		bootpg = gd->ram_size - 4096;

	lmb_reserve(lmb, bootpg, 4096);
}
Ejemplo n.º 7
0
/*
 * On SH machines the conventional approach is to stash system RAM
 * in node 0, and other memory blocks in to node 1 and up, ordered by
 * latency. Each node's pgdat is node-local at the beginning of the node,
 * immediately followed by the node mem map.
 */
void __init setup_memory(void)
{
    unsigned long free_pfn = PFN_UP(__pa(_end));
    u64 base = min_low_pfn << PAGE_SHIFT;
    u64 size = (max_low_pfn << PAGE_SHIFT) - base;

    lmb_add(base, size);

    /* Reserve the LMB regions used by the kernel, initrd, etc.. */
    lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
                (PFN_PHYS(free_pfn) + PAGE_SIZE - 1) -
                (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));

    /*
     * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
     */
    if (CONFIG_ZERO_PAGE_OFFSET != 0)
        lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET);

    lmb_analyze();
    lmb_dump_all();

    /*
     * Node 0 sets up its pgdat at the first available pfn,
     * and bumps it up before setting up the bootmem allocator.
     */
    NODE_DATA(0) = pfn_to_kaddr(free_pfn);
    memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
    free_pfn += PFN_UP(sizeof(struct pglist_data));
    NODE_DATA(0)->bdata = &bootmem_node_data[0];

    /* Set up node 0 */
    setup_bootmem_allocator(free_pfn);

    /* Give the platforms a chance to hook up their nodes */
    plat_mem_setup();
}
Ejemplo n.º 8
0
/*
 * zImage booting support
 */
static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
			char * const argv[], bootm_headers_t *images)
{
	int ret;
	void *zi_start, *zi_end;

	memset(images, 0, sizeof(bootm_headers_t));

	boot_start_lmb(images);

	/* Setup Linux kernel zImage entry point */
	if (argc < 2) {
		images->ep = load_addr;
		debug("*  kernel: default image load address = 0x%08lx\n",
				load_addr);
	} else {
		images->ep = simple_strtoul(argv[1], NULL, 16);
		debug("*  kernel: cmdline image address = 0x%08lx\n",
			images->ep);
	}

	ret = bootz_setup((void *)images->ep, &zi_start, &zi_end);
	if (ret != 0)
		return 1;

	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);

	/* Find ramdisk */
	ret = boot_get_ramdisk(argc, argv, images, IH_INITRD_ARCH,
			&images->rd_start, &images->rd_end);
	if (ret) {
		puts("Ramdisk image is corrupt or invalid\n");
		return 1;
	}

#if defined(CONFIG_OF_LIBFDT)
	/* find flattened device tree */
	ret = boot_get_fdt(flag, argc, argv, images,
			   &images->ft_addr, &images->ft_len);
	if (ret) {
		puts("Could not find a valid device tree\n");
		return 1;
	}

	set_working_fdt_addr(images->ft_addr);
#endif

	return 0;
}
Ejemplo n.º 9
0
/**
 * boot_fdt_add_mem_rsv_regions - Mark the memreserve sections as unusable
 * @lmb: pointer to lmb handle, will be used for memory mgmt
 * @fdt_blob: pointer to fdt blob base address
 *
 * Adds the memreserve regions in the dtb to the lmb block.  Adding the
 * memreserve regions prevents u-boot from using them to store the initrd
 * or the fdt blob.
 */
void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob)
{
	uint64_t addr, size;
	int i, total;

	if (fdt_check_header(fdt_blob) != 0)
		return;

	total = fdt_num_mem_rsv(fdt_blob);
	for (i = 0; i < total; i++) {
		if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0)
			continue;
		printf("   reserving fdt memory region: addr=%llx size=%llx\n",
		       (unsigned long long)addr, (unsigned long long)size);
		lmb_reserve(lmb, addr, size);
	}
}
Ejemplo n.º 10
0
/*
 * Image booting support
 */
static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc,
			char * const argv[], bootm_headers_t *images)
{
	int ret;
	struct Image_header *ih;

	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
			      images, 1);

	/* Setup Linux kernel Image entry point */
	if (!argc) {
		images->ep = load_addr;
		debug("*  kernel: default image load address = 0x%08lx\n",
				load_addr);
	} else {
		images->ep = simple_strtoul(argv[0], NULL, 16);
		debug("*  kernel: cmdline image address = 0x%08lx\n",
			images->ep);
	}

	ret = booti_setup(images);
	if (ret != 0)
		return 1;

	ih = (struct Image_header *)map_sysmem(images->ep, 0);

	lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size));

	unmap_sysmem(ih);

	/*
	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
	 * have a header that provide this informaiton.
	 */
	if (bootm_find_images(flag, argc, argv))
		return 1;

	return 0;
}
Ejemplo n.º 11
0
int image_setup_libfdt(bootm_headers_t *images, void *blob,
		       int of_size, struct lmb *lmb)
{
	ulong *initrd_start = &images->initrd_start;
	ulong *initrd_end = &images->initrd_end;
	int ret;

	if (fdt_chosen(blob, 1) < 0) {
		puts("ERROR: /chosen node create failed");
		puts(" - must RESET the board to recover.\n");
		return -1;
	}
	arch_fixup_memory_node(blob);
	if (IMAGE_OF_BOARD_SETUP)
		ft_board_setup(blob, gd->bd);
	fdt_fixup_ethernet(blob);

	/* Delete the old LMB reservation */
	lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob,
		 (phys_size_t)fdt_totalsize(blob));

	ret = fdt_resize(blob);
	if (ret < 0)
		return ret;
	of_size = ret;

	if (*initrd_start && *initrd_end) {
		of_size += FDT_RAMDISK_OVERHEAD;
		fdt_set_totalsize(blob, of_size);
	}
	/* Create a new LMB reservation */
	lmb_reserve(lmb, (ulong)blob, of_size);

	fdt_initrd(blob, *initrd_start, *initrd_end, 1);
	if (!ft_verify_fdt(blob))
		return -1;

	return 0;
}
Ejemplo n.º 12
0
void __init wii_memory_fixups(void)
{
	struct lmb_property *p = lmb.memory.region;

	/*
	 * This is part of a workaround to allow the use of two
	 * discontinuous RAM ranges on the Wii, even if this is
	 * currently unsupported on 32-bit PowerPC Linux.
	 *
	 * We coalesce the two memory ranges of the Wii into a
	 * single range, then create a reservation for the "hole"
	 * between both ranges.
	 */

	BUG_ON(lmb.memory.cnt != 2);
	BUG_ON(!page_aligned(p[0].base) || !page_aligned(p[1].base));

	p[0].size = _ALIGN_DOWN(p[0].size, PAGE_SIZE);
	p[1].size = _ALIGN_DOWN(p[1].size, PAGE_SIZE);

	wii_hole_start = p[0].base + p[0].size;
	wii_hole_size = p[1].base - wii_hole_start;

	pr_info("MEM1: <%08llx %08llx>\n", p[0].base, p[0].size);
	pr_info("HOLE: <%08lx %08lx>\n", wii_hole_start, wii_hole_size);
	pr_info("MEM2: <%08llx %08llx>\n", p[1].base, p[1].size);

	p[0].size += wii_hole_size + p[1].size;

	lmb.memory.cnt = 1;
	lmb_analyze();

	/* reserve the hole */
	lmb_reserve(wii_hole_start, wii_hole_size);

	/* allow ioremapping the address space in the hole */
	__allow_ioremap_reserved = 1;
}
Ejemplo n.º 13
0
/**
 * boot_relocate_fdt - relocate flat device tree
 * @lmb: pointer to lmb handle, will be used for memory mgmt
 * @of_flat_tree: pointer to a char* variable, will hold fdt start address
 * @of_size: pointer to a ulong variable, will hold fdt length
 *
 * boot_relocate_fdt() allocates a region of memory within the bootmap and
 * relocates the of_flat_tree into that region, even if the fdt is already in
 * the bootmap.  It also expands the size of the fdt by CONFIG_SYS_FDT_PAD
 * bytes.
 *
 * of_flat_tree and of_size are set to final (after relocation) values
 *
 * returns:
 *      0 - success
 *      1 - failure
 */
int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size)
{
	void	*fdt_blob = *of_flat_tree;
	void	*of_start = NULL;
	char	*fdt_high;
	ulong	of_len = 0;
	int	err;
	int	disable_relocation = 0;

	/* nothing to do */
	if (*of_size == 0)
		return 0;

	if (fdt_check_header(fdt_blob) != 0) {
		fdt_error("image is not a fdt");
		goto error;
	}

	/* position on a 4K boundary before the alloc_current */
	/* Pad the FDT by a specified amount */
	of_len = *of_size + CONFIG_SYS_FDT_PAD;

	/* If fdt_high is set use it to select the relocation address */
	fdt_high = getenv("fdt_high");
	if (fdt_high) {
		void *desired_addr = (void *)simple_strtoul(fdt_high, NULL, 16);

		if (((ulong) desired_addr) == ~0UL) {
			/* All ones means use fdt in place */
			of_start = fdt_blob;
			lmb_reserve(lmb, (ulong)of_start, of_len);
			disable_relocation = 1;
		} else if (desired_addr) {
			of_start =
			    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000,
							   (ulong)desired_addr);
			if (of_start == NULL) {
				puts("Failed using fdt_high value for Device Tree");
				goto error;
			}
		} else {
			of_start =
			    (void *)(ulong) lmb_alloc(lmb, of_len, 0x1000);
		}
	} else {
		of_start =
		    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000,
						   getenv_bootm_mapsize()
						   + getenv_bootm_low());
	}

	if (of_start == NULL) {
		puts("device tree - allocation error\n");
		goto error;
	}

	if (disable_relocation) {
		/*
		 * We assume there is space after the existing fdt to use
		 * for padding
		 */
		fdt_set_totalsize(of_start, of_len);
		printf("   Using Device Tree in place at %p, end %p\n",
		       of_start, of_start + of_len - 1);
	} else {
		debug("## device tree at %p ... %p (len=%ld [0x%lX])\n",
		      fdt_blob, fdt_blob + *of_size - 1, of_len, of_len);

		printf("   Loading Device Tree to %p, end %p ... ",
		       of_start, of_start + of_len - 1);

		err = fdt_open_into(fdt_blob, of_start, of_len);
		if (err != 0) {
			fdt_error("fdt move failed");
			goto error;
		}
		puts("OK\n");
	}

	*of_flat_tree = of_start;
	*of_size = of_len;

	set_working_fdt_addr((ulong)*of_flat_tree);
	return 0;

error:
	return 1;
}
Ejemplo n.º 14
0
int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	ulong		iflag;
	ulong		load_end = 0;
	int		ret;
	boot_os_fn	*boot_fn;
#ifdef CONFIG_NEEDS_MANUAL_RELOC
	static int relocated = 0;

	if (!relocated) {
		int i;

		/* relocate boot function table */
		for (i = 0; i < ARRAY_SIZE(boot_os); i++)
			if (boot_os[i] != NULL)
				boot_os[i] += gd->reloc_off;

		/* relocate names of sub-command table */
		for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
			cmd_bootm_sub[i].name += gd->reloc_off;

		relocated = 1;
	}
#endif

	/* determine if we have a sub command */
	if (argc > 1) {
		char *endp;

		simple_strtoul(argv[1], &endp, 16);
		/* endp pointing to NULL means that argv[1] was just a
		 * valid number, pass it along to the normal bootm processing
		 *
		 * If endp is ':' or '#' assume a FIT identifier so pass
		 * along for normal processing.
		 *
		 * Right now we assume the first arg should never be '-'
		 */
		if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
			return do_bootm_subcommand(cmdtp, flag, argc, argv);
	}

	if (bootm_start(cmdtp, flag, argc, argv))
		return 1;

	/*
	 * We have reached the point of no return: we are going to
	 * overwrite all exception vector code, so we cannot easily
	 * recover from any failures any more...
	 */
	iflag = disable_interrupts();

#ifdef CONFIG_NETCONSOLE
	/* Stop the ethernet stack if NetConsole could have left it up */
	eth_halt();
#endif

#if defined(CONFIG_CMD_USB)
	/*
	 * turn off USB to prevent the host controller from writing to the
	 * SDRAM while Linux is booting. This could happen (at least for OHCI
	 * controller), because the HCCA (Host Controller Communication Area)
	 * lies within the SDRAM and the host controller writes continously to
	 * this area (as busmaster!). The HccaFrameNumber is for example
	 * updated every 1 ms within the HCCA structure in SDRAM! For more
	 * details see the OpenHCI specification.
	 */
	usb_stop();
#endif

	ret = bootm_load_os(images.os, &load_end, 1);

	if (ret < 0) {
		if (ret == BOOTM_ERR_RESET)
			do_reset(cmdtp, flag, argc, argv);
		if (ret == BOOTM_ERR_OVERLAP) {
			if (images.legacy_hdr_valid) {
				image_header_t *hdr;
				hdr = &images.legacy_hdr_os_copy;
				if (image_get_type(hdr) == IH_TYPE_MULTI)
					puts("WARNING: legacy format multi "
						"component image "
						"overwritten\n");
			} else {
				puts("ERROR: new format image overwritten - "
					"must RESET the board to recover\n");
				bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
				do_reset(cmdtp, flag, argc, argv);
			}
		}
		if (ret == BOOTM_ERR_UNIMPLEMENTED) {
			if (iflag)
				enable_interrupts();
			bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
			return 1;
		}
	}

	lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));

	if (images.os.type == IH_TYPE_STANDALONE) {
		if (iflag)
			enable_interrupts();
		/* This may return when 'autostart' is 'no' */
		bootm_start_standalone(iflag, argc, argv);
		return 0;
	}

	bootstage_mark(BOOTSTAGE_ID_CHECK_BOOT_OS);

#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
	if (images.os.os == IH_OS_LINUX)
		fixup_silent_linux();
#endif

	boot_fn = boot_os[images.os.os];

	if (boot_fn == NULL) {
		if (iflag)
			enable_interrupts();
		printf("ERROR: booting os '%s' (%d) is not supported\n",
			genimg_get_os_name(images.os.os), images.os.os);
		bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
		return 1;
	}

	arch_preboot_os();

	boot_fn(0, argc, argv, &images);

	bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
#ifdef DEBUG
	puts("\n## Control returned to monitor - resetting...\n");
#endif
	do_reset(cmdtp, flag, argc, argv);

	return 1;
}
Ejemplo n.º 15
0
static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
			char * const argv[])
{
	int ret = 0;
	long state;
	cmd_tbl_t *c;
	boot_os_fn *boot_fn;

	c = find_cmd_tbl(argv[1], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));

	if (c) {
		state = (long)c->cmd;

		/* treat start special since it resets the state machine */
		if (state == BOOTM_STATE_START) {
			argc--;
			argv++;
			return bootm_start(cmdtp, flag, argc, argv);
		}
	} else {
		/* Unrecognized command */
		return CMD_RET_USAGE;
	}

	if (images.state < BOOTM_STATE_START ||
	    images.state >= state) {
		printf("Trying to execute a command out of order\n");
		return CMD_RET_USAGE;
	}

	images.state |= state;
	boot_fn = boot_os[images.os.os];

	switch (state) {
		ulong load_end;
		case BOOTM_STATE_START:
			/* should never occur */
			break;
		case BOOTM_STATE_LOADOS:
			ret = bootm_load_os(images.os, &load_end, 0);
			if (ret)
				return ret;

			lmb_reserve(&images.lmb, images.os.load,
					(load_end - images.os.load));
			break;
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
		case BOOTM_STATE_RAMDISK:
		{
			ulong rd_len = images.rd_end - images.rd_start;

			ret = boot_ramdisk_high(&images.lmb, images.rd_start,
				rd_len, &images.initrd_start, &images.initrd_end);
			if (ret)
				return ret;

			setenv_hex("initrd_start", images.initrd_start);
			setenv_hex("initrd_end", images.initrd_end);
		}
			break;
#endif
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
		case BOOTM_STATE_FDT:
		{
			boot_fdt_add_mem_rsv_regions(&images.lmb,
						     images.ft_addr);
			ret = boot_relocate_fdt(&images.lmb,
				&images.ft_addr, &images.ft_len);
			break;
		}
#endif
		case BOOTM_STATE_OS_CMDLINE:
			ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, &images);
			if (ret)
				printf("cmdline subcommand not supported\n");
			break;
		case BOOTM_STATE_OS_BD_T:
			ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, &images);
			if (ret)
				printf("bdt subcommand not supported\n");
			break;
		case BOOTM_STATE_OS_PREP:
			ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, &images);
			if (ret)
				printf("prep subcommand not supported\n");
			break;
		case BOOTM_STATE_OS_GO:
			disable_interrupts();
#ifdef CONFIG_NETCONSOLE
			/*
			 * Stop the ethernet stack if NetConsole could have
			 * left it up
			 */
			eth_halt();
#endif
			arch_preboot_os();
			boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images);
			break;
	}

	return ret;
}
Ejemplo n.º 16
0
/**
 * Execute selected states of the bootm command.
 *
 * Note the arguments to this state must be the first argument, Any 'bootm'
 * or sub-command arguments must have already been taken.
 *
 * Note that if states contains more than one flag it MUST contain
 * BOOTM_STATE_START, since this handles and consumes the command line args.
 *
 * Also note that aside from boot_os_fn functions and bootm_load_os no other
 * functions we store the return value of in 'ret' may use a negative return
 * value, without special handling.
 *
 * @param cmdtp		Pointer to bootm command table entry
 * @param flag		Command flags (CMD_FLAG_...)
 * @param argc		Number of subcommand arguments (0 = no arguments)
 * @param argv		Arguments
 * @param states	Mask containing states to run (BOOTM_STATE_...)
 * @param images	Image header information
 * @param boot_progress 1 to show boot progress, 0 to not do this
 * @return 0 if ok, something else on error. Some errors will cause this
 *	function to perform a reboot! If states contains BOOTM_STATE_OS_GO
 *	then the intent is to boot an OS, so this function will not return
 *	unless the image type is standalone.
 */
static int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc,
		char * const argv[], int states, bootm_headers_t *images,
		int boot_progress)
{
	boot_os_fn *boot_fn;
	ulong iflag = 0;
	int ret = 0;

	images->state |= states;

	/*
	 * Work through the states and see how far we get. We stop on
	 * any error.
	 */
	if (states & BOOTM_STATE_START)
		ret = bootm_start(cmdtp, flag, argc, argv);

	if (!ret && (states & BOOTM_STATE_FINDOS))
		ret = bootm_find_os(cmdtp, flag, argc, argv);

	if (!ret && (states & BOOTM_STATE_FINDOTHER)) {
		ret = bootm_find_other(cmdtp, flag, argc, argv);
		argc = 0;	/* consume the args */
	}

	/*
	 * We have reached the point of no return: we are going to
	 * overwrite all exception vector code, so we cannot easily
	 * recover from any failures any more...
	 */
	iflag = disable_interrupts();
#ifdef CONFIG_NETCONSOLE
	/* Stop the ethernet stack if NetConsole could have left it up */
	eth_halt();
#endif

#if defined(CONFIG_CMD_USB)
	/*
	 * turn off USB to prevent the host controller from writing to the
	 * SDRAM while Linux is booting. This could happen (at least for OHCI
	 * controller), because the HCCA (Host Controller Communication Area)
	 * lies within the SDRAM and the host controller writes continously to
	 * this area (as busmaster!). The HccaFrameNumber is for example
	 * updated every 1 ms within the HCCA structure in SDRAM! For more
	 * details see the OpenHCI specification.
	 */
	usb_stop();
#endif

	/* Load the OS */
	if (!ret && (states & BOOTM_STATE_LOADOS)) {
		ulong load_end;

		ret = bootm_load_os(images, &load_end, 0);
		if (ret && ret != BOOTM_ERR_OVERLAP)
			goto err;

		if (ret == 0)
			lmb_reserve(&images->lmb, images->os.load,
				    (load_end - images->os.load));
		else if (ret == BOOTM_ERR_OVERLAP)
			ret = 0;
	}

	/* Relocate the ramdisk */
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
	if (!ret && (states & BOOTM_STATE_RAMDISK)) {
		ulong rd_len = images->rd_end - images->rd_start;

		ret = boot_ramdisk_high(&images->lmb, images->rd_start,
			rd_len, &images->initrd_start, &images->initrd_end);
		if (!ret) {
			setenv_hex("initrd_start", images->initrd_start);
			setenv_hex("initrd_end", images->initrd_end);
		}
	}
#endif
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
	if (!ret && (states & BOOTM_STATE_FDT)) {
		boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
		ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
					&images->ft_len);
	}
#endif

	/* From now on, we need the OS boot function */
	if (ret)
		return ret;
	boot_fn = boot_os[images->os.os];
	if (boot_fn == NULL) {
		if (iflag)
			enable_interrupts();
		printf("ERROR: booting os '%s' (%d) is not supported\n",
		       genimg_get_os_name(images->os.os), images->os.os);
		bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
		return 1;
	}

	/* Call various other states that are not generally used */
	if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
		ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
	if (!ret && (states & BOOTM_STATE_OS_BD_T))
		ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
	if (!ret && (states & BOOTM_STATE_OS_PREP))
		ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);

#ifdef CONFIG_TRACE
	/* Pretend to run the OS, then run a user command */
	if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
		char *cmd_list = getenv("fakegocmd");

		ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
				images, boot_fn);
		if (!ret && cmd_list)
			ret = run_command_list(cmd_list, -1, flag);
	}
#endif
	/* Now run the OS! We hope this doesn't return */
	if (!ret && (states & BOOTM_STATE_OS_GO)) {
		ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
				images, boot_fn);
		if (ret)
			goto err;
	}

	return ret;

	/* Deal with any fallout */
err:
	if (iflag)
		enable_interrupts();

	if (ret == BOOTM_ERR_UNIMPLEMENTED)
		bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
	else if (ret == BOOTM_ERR_RESET)
		do_reset(cmdtp, flag, argc, argv);
	else
		puts("subcommand not supported\n");

	return ret;
}
Ejemplo n.º 17
0
/**
 * Execute selected states of the bootm command.
 *
 * Note the arguments to this state must be the first argument, Any 'bootm'
 * or sub-command arguments must have already been taken.
 *
 * Note that if states contains more than one flag it MUST contain
 * BOOTM_STATE_START, since this handles and consumes the command line args.
 *
 * Also note that aside from boot_os_fn functions and bootm_load_os no other
 * functions we store the return value of in 'ret' may use a negative return
 * value, without special handling.
 *
 * @param cmdtp		Pointer to bootm command table entry
 * @param flag		Command flags (CMD_FLAG_...)
 * @param argc		Number of subcommand arguments (0 = no arguments)
 * @param argv		Arguments
 * @param states	Mask containing states to run (BOOTM_STATE_...)
 * @param images	Image header information
 * @param boot_progress 1 to show boot progress, 0 to not do this
 * @return 0 if ok, something else on error. Some errors will cause this
 *	function to perform a reboot! If states contains BOOTM_STATE_OS_GO
 *	then the intent is to boot an OS, so this function will not return
 *	unless the image type is standalone.
 */
static int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc,
		char * const argv[], int states, bootm_headers_t *images,
		int boot_progress)
{
	boot_os_fn *boot_fn;
	ulong iflag = 0;
	int ret = 0, need_boot_fn;

	images->state |= states;

	/*
	 * Work through the states and see how far we get. We stop on
	 * any error.
	 */
	if (states & BOOTM_STATE_START)
		ret = bootm_start(cmdtp, flag, argc, argv);

	if (!ret && (states & BOOTM_STATE_FINDOS))
		ret = bootm_find_os(cmdtp, flag, argc, argv);

	if (!ret && (states & BOOTM_STATE_FINDOTHER)) {
		ret = bootm_find_other(cmdtp, flag, argc, argv);
		argc = 0;	/* consume the args */
	}

	/* Load the OS */
	if (!ret && (states & BOOTM_STATE_LOADOS)) {
		ulong load_end;

		iflag = bootm_disable_interrupts();
		ret = bootm_load_os(images, &load_end, 0);
		if (ret == 0)
			lmb_reserve(&images->lmb, images->os.load,
				    (load_end - images->os.load));
		else if (ret && ret != BOOTM_ERR_OVERLAP)
			goto err;
		else if (ret == BOOTM_ERR_OVERLAP)
			ret = 0;
#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
		if (images->os.os == IH_OS_LINUX)
			fixup_silent_linux();
#endif
	}

	/* Relocate the ramdisk */
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
	if (!ret && (states & BOOTM_STATE_RAMDISK)) {
		ulong rd_len = images->rd_end - images->rd_start;

		ret = boot_ramdisk_high(&images->lmb, images->rd_start,
			rd_len, &images->initrd_start, &images->initrd_end);
		if (!ret) {
			setenv_hex("initrd_start", images->initrd_start);
			setenv_hex("initrd_end", images->initrd_end);
		}
	}
#endif
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
	if (!ret && (states & BOOTM_STATE_FDT)) {
		boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
		ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
					&images->ft_len);
	}
#endif

	/* From now on, we need the OS boot function */
	if (ret)
		return ret;
	boot_fn = boot_os[images->os.os];
	need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE |
			BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP |
			BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO);
	if (boot_fn == NULL && need_boot_fn) {
		if (iflag)
			enable_interrupts();
		printf("ERROR: booting os '%s' (%d) is not supported\n",
		       genimg_get_os_name(images->os.os), images->os.os);
		bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
		return 1;
	}

	/* Call various other states that are not generally used */
	if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
		ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
	if (!ret && (states & BOOTM_STATE_OS_BD_T))
		ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
	if (!ret && (states & BOOTM_STATE_OS_PREP))
		ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);

#ifdef CONFIG_TRACE
	/* Pretend to run the OS, then run a user command */
	if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
		char *cmd_list = getenv("fakegocmd");

		ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
				images, boot_fn);
		if (!ret && cmd_list)
			ret = run_command_list(cmd_list, -1, flag);
	}
#endif

	/* Check for unsupported subcommand. */
	if (ret) {
		puts("subcommand not supported\n");
		return ret;
	}

	/* Now run the OS! We hope this doesn't return */
	if (!ret && (states & BOOTM_STATE_OS_GO))
		ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
				images, boot_fn);

	/* Deal with any fallout */
err:
	if (iflag)
		enable_interrupts();

	if (ret == BOOTM_ERR_UNIMPLEMENTED)
		bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
	else if (ret == BOOTM_ERR_RESET)
		do_reset(cmdtp, flag, argc, argv);

	return ret;
}
Ejemplo n.º 18
0
static void __init build_iSeries_Memory_Map(void)
{
	u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize;
	u32 nextPhysChunk;
	u32 hptFirstChunk, hptLastChunk, hptSizeChunks, hptSizePages;
	u32 num_ptegs;
	u32 totalChunks,moreChunks;
	u32 currChunk, thisChunk, absChunk;
	u32 currDword;
	u32 chunkBit;
	u64 map;
	struct MemoryBlock mb[32];
	unsigned long numMemoryBlocks, curBlock;

	/* Chunk size on iSeries is 256K bytes */
	totalChunks = (u32)HvLpConfig_getMsChunks();
	klimit = msChunks_alloc(klimit, totalChunks, 1UL<<18);

	/* Get absolute address of our load area
	 * and map it to physical address 0
	 * This guarantees that the loadarea ends up at physical 0
	 * otherwise, it might not be returned by PLIC as the first
	 * chunks
	 */
	
	loadAreaFirstChunk = (u32)addr_to_chunk(itLpNaca.xLoadAreaAddr);
	loadAreaSize =  itLpNaca.xLoadAreaChunks;

	/* Only add the pages already mapped here.  
	 * Otherwise we might add the hpt pages 
	 * The rest of the pages of the load area
	 * aren't in the HPT yet and can still
	 * be assigned an arbitrary physical address
	 */
	if ( (loadAreaSize * 64) > HvPagesToMap )
		loadAreaSize = HvPagesToMap / 64;

	loadAreaLastChunk = loadAreaFirstChunk + loadAreaSize - 1;

	/* TODO Do we need to do something if the HPT is in the 64MB load area?
	 * This would be required if the itLpNaca.xLoadAreaChunks includes 
	 * the HPT size
	 */

	printk( "Mapping load area - physical addr = 0000000000000000\n"
                "                    absolute addr = %016lx\n", 
			chunk_to_addr(loadAreaFirstChunk) );
	printk( "Load area size %dK\n", loadAreaSize*256 );
	
	for (	nextPhysChunk = 0; 
		nextPhysChunk < loadAreaSize; 
		++nextPhysChunk ) {
		msChunks.abs[nextPhysChunk] = loadAreaFirstChunk+nextPhysChunk;
	}
	
	/* Get absolute address of our HPT and remember it so
	 * we won't map it to any physical address
	 */

	hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress());
	hptSizePages =  (u32)(HvCallHpt_getHptPages());
	hptSizeChunks = hptSizePages >> (msChunks.chunk_shift-PAGE_SHIFT);
	hptLastChunk = hptFirstChunk + hptSizeChunks - 1;
	
	printk( "HPT absolute addr = %016lx, size = %dK\n",
			chunk_to_addr(hptFirstChunk), hptSizeChunks*256 );

	/* Fill in the htab_data structure */
	
	/* Fill in size of hashed page table */
	num_ptegs = hptSizePages * (PAGE_SIZE/(sizeof(HPTE)*HPTES_PER_GROUP));
	htab_data.htab_num_ptegs = num_ptegs;
	htab_data.htab_hash_mask = num_ptegs - 1;
	
	/* The actual hashed page table is in the hypervisor, we have no direct access */
	htab_data.htab = NULL;

	/* Determine if absolute memory has any
	 * holes so that we can interpret the
	 * access map we get back from the hypervisor
	 * correctly.
	 */
	numMemoryBlocks = iSeries_process_mainstore_vpd( mb, 32 );

	/* Process the main store access map from the hypervisor
	 * to build up our physical -> absolute translation table
	 */
	curBlock = 0;
	currChunk = 0;
	currDword = 0;
	moreChunks = totalChunks;

	while ( moreChunks ) {
		map = HvCallSm_get64BitsOfAccessMap( itLpNaca.xLpIndex,
						     currDword );
		thisChunk = currChunk;
		while ( map ) {
			chunkBit = map >> 63;
			map <<= 1;
			if ( chunkBit ) {
				--moreChunks;

				while ( thisChunk >= mb[curBlock].logicalEnd ) {
					++curBlock;
					if ( curBlock >= numMemoryBlocks )
						panic("out of memory blocks");
				}
				if ( thisChunk < mb[curBlock].logicalStart )
					panic("memory block error");

				absChunk = mb[curBlock].absStart + ( thisChunk - mb[curBlock].logicalStart );

				if ( ( ( absChunk < hptFirstChunk ) ||
				       ( absChunk > hptLastChunk ) ) &&
				     ( ( absChunk < loadAreaFirstChunk ) ||
				       ( absChunk > loadAreaLastChunk ) ) ) {
					msChunks.abs[nextPhysChunk] = absChunk;
					++nextPhysChunk;
				}
			}
			++thisChunk;
		}
		++currDword;
		currChunk += 64;
	}
					
	/* main store size (in chunks) is 
	 *   totalChunks - hptSizeChunks
	 * which should be equal to 
	 *   nextPhysChunk
	 */
	naca->physicalMemorySize = chunk_to_addr(nextPhysChunk);

	/* Bolt kernel mappings for all of memory */
	iSeries_bolt_kernel( 0, naca->physicalMemorySize );

	lmb_init();
	lmb_add( 0, naca->physicalMemorySize );
	lmb_analyze();	/* ?? */
	lmb_reserve( 0, __pa(klimit));

	/* 
	 * Hardcode to GP size.  I am not sure where to get this info. DRENG
	 */
	naca->slb_size = 64;
}
Ejemplo n.º 19
0
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	ulong		iflag;
	ulong		load_end = 0;
	int		ret;
	boot_os_fn	*boot_fn;

#ifdef CONFIG_SECURE_BOOT
#ifndef CONFIG_SECURE_BL1_ONLY
	security_check();
#endif
#endif

	char cmdbuffer[64];
	sprintf(cmdbuffer,"sdfuse autocheck");
	run_command(cmdbuffer, 0);
	exynos4412_screen_backlight(0);

#ifdef CONFIG_ZIMAGE_BOOT
#define LINUX_ZIMAGE_MAGIC	0x016f2818
	image_header_t	*hdr;
	ulong		addr;

	/* find out kernel image address */
	if (argc < 2) {
		addr = load_addr;
		debug ("*  kernel: default image load address = 0x%08lx\n",
				load_addr);
	} else {
		addr = simple_strtoul(argv[1], NULL, 16);
	}

	if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) {
		u32 val;
		printf("Boot with zImage\n");

		//addr = virt_to_phys(addr);
		hdr = (image_header_t *)addr;
		hdr->ih_os = IH_OS_LINUX;
		hdr->ih_ep = ntohl(addr);
		
		memmove (&images.legacy_hdr_os_copy, hdr, sizeof(image_header_t));

		/* save pointer to image header */
		images.legacy_hdr_os = hdr;

		images.legacy_hdr_valid = 1;

		goto after_header_check;
	}
#endif

#ifdef CONFIG_NEEDS_MANUAL_RELOC
	static int relocated = 0;

	/* relocate boot function table */
	if (!relocated) {
		int i;
		for (i = 0; i < ARRAY_SIZE(boot_os); i++)
			if (boot_os[i] != NULL)
				boot_os[i] += gd->reloc_off;
		relocated = 1;
	}
#endif

	/* determine if we have a sub command */
	if (argc > 1) {
		char *endp;

		simple_strtoul(argv[1], &endp, 16);
		/* endp pointing to NULL means that argv[1] was just a
		 * valid number, pass it along to the normal bootm processing
		 *
		 * If endp is ':' or '#' assume a FIT identifier so pass
		 * along for normal processing.
		 *
		 * Right now we assume the first arg should never be '-'
		 */
		if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
			return do_bootm_subcommand(cmdtp, flag, argc, argv);
	}

	if (bootm_start(cmdtp, flag, argc, argv))
		return 1;

	/*
	 * We have reached the point of no return: we are going to
	 * overwrite all exception vector code, so we cannot easily
	 * recover from any failures any more...
	 */
	iflag = disable_interrupts();

#if defined(CONFIG_CMD_USB)
	/*
	 * turn off USB to prevent the host controller from writing to the
	 * SDRAM while Linux is booting. This could happen (at least for OHCI
	 * controller), because the HCCA (Host Controller Communication Area)
	 * lies within the SDRAM and the host controller writes continously to
	 * this area (as busmaster!). The HccaFrameNumber is for example
	 * updated every 1 ms within the HCCA structure in SDRAM! For more
	 * details see the OpenHCI specification.
	 */
	usb_stop();
#endif

	ret = bootm_load_os(images.os, &load_end, 1);

	if (ret < 0) {
		if (ret == BOOTM_ERR_RESET)
			do_reset (cmdtp, flag, argc, argv);
		if (ret == BOOTM_ERR_OVERLAP) {
			if (images.legacy_hdr_valid) {
				if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
					puts ("WARNING: legacy format multi component "
						"image overwritten\n");
			} else {
				puts ("ERROR: new format image overwritten - "
					"must RESET the board to recover\n");
				show_boot_progress (-113);
				do_reset (cmdtp, flag, argc, argv);
			}
		}
		if (ret == BOOTM_ERR_UNIMPLEMENTED) {
			if (iflag)
				enable_interrupts();
			show_boot_progress (-7);
			return 1;
		}
	}

	lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));

	if (images.os.type == IH_TYPE_STANDALONE) {
		if (iflag)
			enable_interrupts();
		/* This may return when 'autostart' is 'no' */
		bootm_start_standalone(iflag, argc, argv);
		return 0;
	}

	show_boot_progress (8);

#if defined(CONFIG_ZIMAGE_BOOT)
after_header_check:
	images.os.os = hdr->ih_os;
	images.ep = image_get_ep (&images.legacy_hdr_os_copy);
#endif

#ifdef CONFIG_SILENT_CONSOLE
	if (images.os.os == IH_OS_LINUX)
		fixup_silent_linux();
#endif

	boot_fn = boot_os[images.os.os];

	if (boot_fn == NULL) {
		if (iflag)
			enable_interrupts();
		printf ("ERROR: booting os '%s' (%d) is not supported\n",
			genimg_get_os_name(images.os.os), images.os.os);
		show_boot_progress (-8);
		return 1;
	}

	arch_preboot_os();

	boot_fn(0, argc, argv, &images);

	show_boot_progress (-9);
#ifdef DEBUG
	puts ("\n## Control returned to monitor - resetting...\n");
#endif
	do_reset (cmdtp, flag, argc, argv);

	return 1;
}
Ejemplo n.º 20
0
int image_setup_libfdt(bootm_headers_t *images, void *blob,
		       int of_size, struct lmb *lmb)
{
	ulong *initrd_start = &images->initrd_start;
	ulong *initrd_end = &images->initrd_end;
	int ret = -EPERM;
	int fdt_ret;

	if (fdt_root(blob) < 0) {
		printf("ERROR: root node setup failed\n");
		goto err;
	}
	if (fdt_chosen(blob) < 0) {
		printf("ERROR: /chosen node create failed\n");
		goto err;
	}
	if (arch_fixup_fdt(blob) < 0) {
		printf("ERROR: arch-specific fdt fixup failed\n");
		goto err;
	}
	if (IMAGE_OF_BOARD_SETUP) {
		fdt_ret = ft_board_setup(blob, gd->bd);
		if (fdt_ret) {
			printf("ERROR: board-specific fdt fixup failed: %s\n",
			       fdt_strerror(fdt_ret));
			goto err;
		}
	}
	if (IMAGE_OF_SYSTEM_SETUP) {
		fdt_ret = ft_system_setup(blob, gd->bd);
		if (fdt_ret) {
			printf("ERROR: system-specific fdt fixup failed: %s\n",
			       fdt_strerror(fdt_ret));
			goto err;
		}
	}
	fdt_fixup_ethernet(blob);

	/* Delete the old LMB reservation */
	lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob,
		 (phys_size_t)fdt_totalsize(blob));

	ret = fdt_shrink_to_minimum(blob);
	if (ret < 0)
		goto err;
	of_size = ret;

	if (*initrd_start && *initrd_end) {
		of_size += FDT_RAMDISK_OVERHEAD;
		fdt_set_totalsize(blob, of_size);
	}
	/* Create a new LMB reservation */
	lmb_reserve(lmb, (ulong)blob, of_size);

	fdt_initrd(blob, *initrd_start, *initrd_end);
	if (!ft_verify_fdt(blob))
		goto err;

#if defined(CONFIG_SOC_KEYSTONE)
	if (IMAGE_OF_BOARD_SETUP)
		ft_board_setup_ex(blob, gd->bd);
#endif

	return 0;
err:
	printf(" - must RESET the board to recover.\n\n");

	return ret;
}
Ejemplo n.º 21
0
int do_bootm_subcommand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	int ret = 0;
	int state;
	cmd_tbl_t *c;
	boot_os_fn *boot_fn;

	c = find_cmd_tbl(argv[1], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));

	if (c) {
		state = (int)c->cmd;

		/* treat start special since it resets the state machine */
		if (state == BOOTM_STATE_START) {
			argc--;
			argv++;
			return bootm_start(cmdtp, flag, argc, argv);
		}
	}
	/* Unrecognized command */
	else {
		cmd_usage(cmdtp);
		return 1;
	}

	if (images.state >= state) {
		printf ("Trying to execute a command out of order\n");
		cmd_usage(cmdtp);
		return 1;
	}

	images.state |= state;
	boot_fn = boot_os[images.os.os];

	switch (state) {
		ulong load_end;
		case BOOTM_STATE_START:
			/* should never occur */
			break;
		case BOOTM_STATE_LOADOS:
			ret = bootm_load_os(images.os, &load_end, 0);
			if (ret)
				return ret;

			lmb_reserve(&images.lmb, images.os.load,
					(load_end - images.os.load));
			break;
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC)
		case BOOTM_STATE_RAMDISK:
		{
			ulong rd_len = images.rd_end - images.rd_start;
			char str[17];

			ret = boot_ramdisk_high(&images.lmb, images.rd_start,
				rd_len, &images.initrd_start, &images.initrd_end);
			if (ret)
				return ret;

			sprintf(str, "%lx", images.initrd_start);
			setenv("initrd_start", str);
			sprintf(str, "%lx", images.initrd_end);
			setenv("initrd_end", str);
		}
			break;
#endif
#ifdef CONFIG_OF_LIBFDT
		case BOOTM_STATE_FDT:
		{
			ulong bootmap_base = getenv_bootm_low();
			ret = boot_relocate_fdt(&images.lmb, bootmap_base,
				&images.ft_addr, &images.ft_len);
			break;
		}
#endif
		case BOOTM_STATE_OS_CMDLINE:
			ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, &images);
			if (ret)
				printf ("cmdline subcommand not supported\n");
			break;
		case BOOTM_STATE_OS_BD_T:
			ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, &images);
			if (ret)
				printf ("bdt subcommand not supported\n");
			break;
		case BOOTM_STATE_OS_PREP:
			ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, &images);
			if (ret)
				printf ("prep subcommand not supported\n");
			break;
		case BOOTM_STATE_OS_GO:
			disable_interrupts();
			boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images);
			break;
	}

	return ret;
}
Ejemplo n.º 22
0
/*static*/ void __init iSeries_init_early(void)
{
	extern unsigned long memory_limit;

	DBG(" -> iSeries_init_early()\n");

	ppcdbg_initialize();

#if defined(CONFIG_BLK_DEV_INITRD)
	/*
	 * If the init RAM disk has been configured and there is
	 * a non-zero starting address for it, set it up
	 */
	if (naca->xRamDisk) {
		initrd_start = (unsigned long)__va(naca->xRamDisk);
		initrd_end = initrd_start + naca->xRamDiskSize * PAGE_SIZE;
		initrd_below_start_ok = 1;	// ramdisk in kernel space
		ROOT_DEV = Root_RAM0;
		if (((rd_size * 1024) / PAGE_SIZE) < naca->xRamDiskSize)
			rd_size = (naca->xRamDiskSize * PAGE_SIZE) / 1024;
	} else
#endif /* CONFIG_BLK_DEV_INITRD */
	{
	    /* ROOT_DEV = MKDEV(VIODASD_MAJOR, 1); */
	}

	iSeries_recal_tb = get_tb();
	iSeries_recal_titan = HvCallXm_loadTod();

	/*
	 * Cache sizes must be initialized before hpte_init_iSeries is called
	 * as the later need them for flush_icache_range()
	 */
	setup_iSeries_cache_sizes();

	/*
	 * Initialize the hash table management pointers
	 */
	hpte_init_iSeries();

	/*
	 * Initialize the DMA/TCE management
	 */
	tce_init_iSeries();

	/*
	 * Initialize the table which translate Linux physical addresses to
	 * AS/400 absolute addresses
	 */
	build_iSeries_Memory_Map();

	iSeries_get_cmdline();

	/* Save unparsed command line copy for /proc/cmdline */
	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);

	/* Parse early parameters, in particular mem=x */
	parse_early_param();

	if (memory_limit) {
		if (memory_limit < systemcfg->physicalMemorySize)
			systemcfg->physicalMemorySize = memory_limit;
		else {
			printk("Ignoring mem=%lu >= ram_top.\n", memory_limit);
			memory_limit = 0;
		}
	}

	/* Bolt kernel mappings for all of memory (or just a bit if we've got a limit) */
	iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);

	lmb_init();
	lmb_add(0, systemcfg->physicalMemorySize);
	lmb_analyze();
	lmb_reserve(0, __pa(klimit));

	/* Initialize machine-dependency vectors */
#ifdef CONFIG_SMP
	smp_init_iSeries();
#endif
	if (itLpNaca.xPirEnvironMode == 0) 
		piranha_simulator = 1;

	/* Associate Lp Event Queue 0 with processor 0 */
	HvCallEvent_setLpEventQueueInterruptProc(0, 0);

	mf_init();
	mf_initialized = 1;
	mb();

	/* If we were passed an initrd, set the ROOT_DEV properly if the values
	 * look sensible. If not, clear initrd reference.
	 */
#ifdef CONFIG_BLK_DEV_INITRD
	if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
	    initrd_end > initrd_start)
		ROOT_DEV = Root_RAM0;
	else
		initrd_start = initrd_end = 0;
#endif /* CONFIG_BLK_DEV_INITRD */

	DBG(" <- iSeries_init_early()\n");
}
Ejemplo n.º 23
0
/*
 * We need to stop things allocating the low memory; ideally we need a
 * better implementation of GFP_DMA which does not assume that DMA-able
 * memory starts at zero.
 */
void __init integrator_reserve(void)
{
    lmb_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
}
Ejemplo n.º 24
0
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	ulong		iflag;
	ulong		load_end = 0;
	int		    ret = 0;
	boot_os_fn	*boot_fn;

	AML_LOG_INIT("cmd_bootm");
	AML_LOG_TE("cmd_bootm");
	
#ifdef TEST_UBOOT_BOOT_SPEND_TIME
	bootm_start_time = get_utimer(0);
#endif

#ifdef CONFIG_NEEDS_MANUAL_RELOC
	static int relocated = 0;

	/* relocate boot function table */
	if (!relocated) {
		int i;
		for (i = 0; i < ARRAY_SIZE(boot_os); i++)
			if (boot_os[i] != NULL)
				boot_os[i] += gd->reloc_off;
		relocated = 1;
	}
#endif

	AML_LOG_TE("cmd_bootm");

#ifdef CONFIG_RESET_TO_SYSTEM
    struct aml_pmu_driver *pmu_driver = NULL;
    pmu_driver = aml_pmu_get_driver();
    if (pmu_driver && pmu_driver->pmu_reset_flag_operation) {
        pmu_driver->pmu_reset_flag_operation(RESET_FLAG_SET);
    }
#endif

	AML_LOG_TE("cmd_bootm");

#ifdef CONFIG_M6_SECU_BOOT
#ifdef CONFIG_MESON_TRUSTZONE
	extern int meson_trustzone_boot_check(unsigned char *addr);
	ret = meson_trustzone_boot_check((unsigned char*)load_addr);
#else
	extern int aml_decrypt_kernel_image(void* kernel_image_address);
	ret = aml_decrypt_kernel_image((void*)load_addr);
#endif
	if(ret != 0)
	{
		printf("Error! Illegal kernel image, please check!\n");
		return ret;
	}		
#endif //CONFIG_M6_SECU_BOOT


	AML_LOG_TE("cmd_bootm");

#ifdef CONFIG_AML_SECU_BOOT_V2
#ifdef CONFIG_MESON_TRUSTZONE
	extern int meson_trustzone_boot_check(unsigned char *addr);
	if(!g_nIMGReadFlag)
	ret = meson_trustzone_boot_check(aml_get_kernel_crypto_addr(argc < 2 ? NULL : argv[1]));
#else
	extern int aml_sec_boot_check(unsigned char *pSRC);
	if(!g_nIMGReadFlag)
	ret = aml_sec_boot_check(aml_get_kernel_crypto_addr(argc < 2 ? NULL : argv[1]));
#endif
	if(0 != ret)
		return ret;	
#endif //CONFIG_AML_SECU_BOOT_V2


	AML_LOG_TE("cmd_bootm");

#ifdef CONFIG_AML_GATE_INIT
		extern void gate_init(void);
		gate_init();
#endif

	/* determine if we have a sub command */
	if (argc > 1) {
		char *endp;

		simple_strtoul(argv[1], &endp, 16);
		/* endp pointing to NULL means that argv[1] was just a
		 * valid number, pass it along to the normal bootm processing
		 *
		 * If endp is ':' or '#' assume a FIT identifier so pass
		 * along for normal processing.
		 *
		 * Right now we assume the first arg should never be '-'
		 */
		if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
			return do_bootm_subcommand(cmdtp, flag, argc, argv);
	}

	AML_LOG_TE("cmd_bootm");

	if (bootm_start(cmdtp, flag, argc, argv))
		return 1;

	AML_LOG_TE("cmd_bootm");

	/*
	 * We have reached the point of no return: we are going to
	 * overwrite all exception vector code, so we cannot easily
	 * recover from any failures any more...
	 */
	iflag = disable_interrupts();

#if defined(CONFIG_CMD_USB)
	/*
	 * turn off USB to prevent the host controller from writing to the
	 * SDRAM while Linux is booting. This could happen (at least for OHCI
	 * controller), because the HCCA (Host Controller Communication Area)
	 * lies within the SDRAM and the host controller writes continously to
	 * this area (as busmaster!). The HccaFrameNumber is for example
	 * updated every 1 ms within the HCCA structure in SDRAM! For more
	 * details see the OpenHCI specification.
	 */
	usb_stop();
#endif

	AML_LOG_TE("cmd_bootm");

	ret = bootm_load_os(images.os, &load_end, 1);

	AML_LOG_TE("cmd_bootm");

	if (ret < 0) {
		if (ret == BOOTM_ERR_RESET)
			do_reset (cmdtp, flag, argc, argv);
		if (ret == BOOTM_ERR_OVERLAP) {
			if (images.legacy_hdr_valid) {
				if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
					puts ("WARNING: legacy format multi component "
						"image overwritten\n");
			} else {
				puts ("ERROR: new format image overwritten - "
					"must RESET the board to recover\n");
				show_boot_progress (-113);
				do_reset (cmdtp, flag, argc, argv);
			}
		}
		if (ret == BOOTM_ERR_UNIMPLEMENTED) {
			if (iflag)
				enable_interrupts();
			show_boot_progress (-7);
			return 1;
		}
	}

	AML_LOG_TE("cmd_bootm");

	lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));

	AML_LOG_TE("cmd_bootm");

	if (images.os.type == IH_TYPE_STANDALONE) {
		if (iflag)
			enable_interrupts();
		/* This may return when 'autostart' is 'no' */
		bootm_start_standalone(iflag, argc, argv);
		return 0;
	}

	show_boot_progress (8);

#if defined(CONFIG_SILENT_CONSOLE) &&  \
	(defined(CONFIG_SILENT_CONSOLE_LINUX_QUIET) || defined(CONFIG_DEPRECATED_SILENT_LINUX_CONSOLE))
	if (images.os.os == IH_OS_LINUX)
		fixup_silent_linux();
#endif

	AML_LOG_TE("cmd_bootm");

#ifdef CONFIG_AUTO_SET_BOOTARGS_MEM
	mem_size_arg_process();
#endif

	boot_fn = boot_os[images.os.os];

	if (boot_fn == NULL) {
		if (iflag)
			enable_interrupts();
		printf ("ERROR: booting os '%s' (%d) is not supported\n",
			genimg_get_os_name(images.os.os), images.os.os);
		show_boot_progress (-8);
		return 1;
	}

	AML_LOG_TE("cmd_bootm");

	arch_preboot_os();

#ifdef TEST_UBOOT_BOOT_SPEND_TIME
	{   int boot_kernel_start;
	    boot_kernel_start = get_utimer(0);
	    printf("bootm start to prepare boot kernel time:%dus\n",boot_kernel_start-bootm_start_time);
	    printf("from main_loop start to kernel decompress finished time:%dus\n",boot_kernel_start-main_loop_start);
	}
#endif
	ulong	temp_img_addr;

	AML_LOG_TE("cmd_bootm");

	/* use fprintf to always show this print even if console is silenced with GD_FLG_SILENT */
	fprintf(stderr, "uboot time: %d us.\n", get_utimer(0));
	boot_fn(0, argc, argv, &images);

	show_boot_progress (-9);
#ifdef DEBUG
	puts ("\n## Control returned to monitor - resetting...\n");
#endif
	do_reset (cmdtp, flag, argc, argv);

	return 1;
}
/* Reserve screen memory region at the start of main system memory. */
static void __init edb7211_reserve(void)
{
	lmb_reserve(PHYS_OFFSET, 0x00020000);
}
Ejemplo n.º 26
0
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	image_header_t	*hdr;
	ulong		addr;
	ulong		iflag;
	const char	*type_name;
	uint		unc_len = CONFIG_SYS_BOOTM_LEN;
	uint8_t		comp, type, os;

	void		*os_hdr;
	ulong		os_data, os_len;
	ulong		image_start, image_end;
	ulong		load_start, load_end;
	ulong		mem_start;
	phys_size_t	mem_size;

	struct lmb lmb;

#if defined(CONFIG_SECURE_BOOT)
	int rv;
#endif

#if defined(CONFIG_SECURE_BOOT)
	rv = Check_Signature( (SecureBoot_CTX *)SECURE_BOOT_CONTEXT_ADDR,
                                (unsigned char*)CONFIG_SECURE_KERNEL_BASE,
                                CONFIG_SECURE_KERNEL_SIZE-128,
                                (unsigned char*)(CONFIG_SECURE_KERNEL_BASE+CONFIG_SECURE_KERNEL_SIZE-128),
                                128 );
        if(rv != SB_OK) {
                printf("Kernel Integrity check fail\nSystem Halt....");
                while(1);
        }
        printf("Kernel Integirty check success.\n");

	rv = Check_Signature( (SecureBoot_CTX *)SECURE_BOOT_CONTEXT_ADDR,
                                (unsigned char*)CONFIG_SECURE_ROOTFS_BASE,
                                CONFIG_SECURE_ROOTFS_SIZE-128,
                                (unsigned char*)(CONFIG_SECURE_ROOTFS_BASE+CONFIG_SECURE_ROOTFS_SIZE-128),
                                128 );
	if(rv != SB_OK) {
                printf("rootfs Integrity check fail\nSystem Halt....");
                while(1);
        }

        printf("rootfs Integirty check success.\n");

#endif
	
	memset ((void *)&images, 0, sizeof (images));
	images.verify = getenv_yesno ("verify");
//	images.lmb = &lmb;
	memcpy (&images.lmb, &lmb, sizeof(struct lmb));

	lmb_init(&lmb);

	mem_start = getenv_bootm_low();
	mem_size = getenv_bootm_size();

	lmb_add(&lmb, (phys_addr_t)mem_start, mem_size);

	board_lmb_reserve(&lmb);

#ifdef CONFIG_ZIMAGE_BOOT
#define LINUX_ZIMAGE_MAGIC	0x016f2818
	/* find out kernel image address */
	if (argc < 2) {
		addr = load_addr;
		debug ("*  kernel: default image load address = 0x%08lx\n",
				load_addr);
	} else {
		addr = simple_strtoul(argv[1], NULL, 16);
		//debug ("*  kernel: cmdline image address = 0x%08lx\n", img_addr);
	}


	if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) {
		printf("Boot with zImage\n");
		addr = virt_to_phys(addr);
		hdr = (image_header_t *)addr;
		hdr->ih_os = IH_OS_LINUX;
		hdr->ih_ep = ntohl(addr);

		memmove (&images.legacy_hdr_os_copy, hdr, sizeof(image_header_t));

		/* save pointer to image header */
		images.legacy_hdr_os = hdr;

		images.legacy_hdr_valid = 1;

		goto after_header_check;
	}
#endif

	/* get kernel image header, start address and length */
	os_hdr = boot_get_kernel (cmdtp, flag, argc, argv,
			&images, &os_data, &os_len);
	if (os_len == 0) {
		puts ("ERROR: can't get kernel image!\n");
		return 1;
	}

	/* get image parameters */
	switch (genimg_get_format (os_hdr)) {
	case IMAGE_FORMAT_LEGACY:
		type = image_get_type (os_hdr);
		comp = image_get_comp (os_hdr);
		os = image_get_os (os_hdr);

		image_end = image_get_image_end (os_hdr);
		load_start = image_get_load (os_hdr);
		break;
#if defined(CONFIG_FIT)
	case IMAGE_FORMAT_FIT:
		if (fit_image_get_type (images.fit_hdr_os,
					images.fit_noffset_os, &type)) {
			puts ("Can't get image type!\n");
			show_boot_progress (-109);
			return 1;
		}

		if (fit_image_get_comp (images.fit_hdr_os,
					images.fit_noffset_os, &comp)) {
			puts ("Can't get image compression!\n");
			show_boot_progress (-110);
			return 1;
		}

		if (fit_image_get_os (images.fit_hdr_os,
					images.fit_noffset_os, &os)) {
			puts ("Can't get image OS!\n");
			show_boot_progress (-111);
			return 1;
		}

		image_end = fit_get_end (images.fit_hdr_os);

		if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os,
					&load_start)) {
			puts ("Can't get image load address!\n");
			show_boot_progress (-112);
			return 1;
		}
		break;
#endif
	default:
		puts ("ERROR: unknown image format type!\n");
		return 1;
	}

	image_start = (ulong)os_hdr;
	load_end = 0;
	type_name = genimg_get_type_name (type);

	/*
	 * We have reached the point of no return: we are going to
	 * overwrite all exception vector code, so we cannot easily
	 * recover from any failures any more...
	 */
	iflag = disable_interrupts();

#if defined(CONFIG_CMD_USB)
	/*
	 * turn off USB to prevent the host controller from writing to the
	 * SDRAM while Linux is booting. This could happen (at least for OHCI
	 * controller), because the HCCA (Host Controller Communication Area)
	 * lies within the SDRAM and the host controller writes continously to
	 * this area (as busmaster!). The HccaFrameNumber is for example
	 * updated every 1 ms within the HCCA structure in SDRAM! For more
	 * details see the OpenHCI specification.
	 */
	usb_stop();
#endif


#ifdef CONFIG_AMIGAONEG3SE
	/*
	 * We've possible left the caches enabled during
	 * bios emulation, so turn them off again
	 */
	icache_disable();
	invalidate_l1_instruction_cache();
	flush_data_cache();
	dcache_disable();
#endif

	switch (comp) {
	case IH_COMP_NONE:
		if (load_start == (ulong)os_hdr) {
			printf ("   XIP %s ... ", type_name);
		} else {
			printf ("   Loading %s ... ", type_name);

			memmove_wd ((void *)load_start,
				   (void *)os_data, os_len, CHUNKSZ);
		}
		load_end = load_start + os_len;
		puts("OK\n");
		break;
	case IH_COMP_GZIP:
		printf ("   Uncompressing %s ... ", type_name);
		if (gunzip ((void *)load_start, unc_len,
					(uchar *)os_data, &os_len) != 0) {
			puts ("GUNZIP: uncompress or overwrite error "
				"- must RESET board to recover\n");
			show_boot_progress (-6);
			do_reset (cmdtp, flag, argc, argv);
		}

		load_end = load_start + os_len;
		break;
#ifdef CONFIG_BZIP2
	case IH_COMP_BZIP2:
		printf ("   Uncompressing %s ... ", type_name);
		/*
		 * If we've got less than 4 MB of malloc() space,
		 * use slower decompression algorithm which requires
		 * at most 2300 KB of memory.
		 */
		int i = BZ2_bzBuffToBuffDecompress ((char*)load_start,
					&unc_len, (char *)os_data, os_len,
					CFG_MALLOC_LEN < (4096 * 1024), 0);
		if (i != BZ_OK) {
			printf ("BUNZIP2: uncompress or overwrite error %d "
				"- must RESET board to recover\n", i);
			show_boot_progress (-6);
			do_reset (cmdtp, flag, argc, argv);
		}

		load_end = load_start + unc_len;
		break;
#endif /* CONFIG_BZIP2 */
	default:
		if (iflag)
			enable_interrupts();
		printf ("Unimplemented compression type %d\n", comp);
		show_boot_progress (-7);
		return 1;
	}
	puts ("OK\n");
	debug ("   kernel loaded at 0x%08lx, end = 0x%08lx\n", load_start, load_end);
	show_boot_progress (7);

	if ((load_start < image_end) && (load_end > image_start)) {
		debug ("image_start = 0x%lX, image_end = 0x%lx\n", image_start, image_end);
		debug ("load_start = 0x%lx, load_end = 0x%lx\n", load_start, load_end);

		if (images.legacy_hdr_valid) {
			if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
				puts ("WARNING: legacy format multi component "
					"image overwritten\n");
		} else {
			puts ("ERROR: new format image overwritten - "
				"must RESET the board to recover\n");
			show_boot_progress (-113);
			do_reset (cmdtp, flag, argc, argv);
		}
	}

	show_boot_progress (8);

	lmb_reserve(&lmb, load_start, (load_end - load_start));

#if defined(CONFIG_ZIMAGE_BOOT)
after_header_check:
	os = hdr->ih_os;
#endif

	switch (os) {
	default:			/* handled by (original) Linux case */
	case IH_OS_LINUX:
#ifdef CONFIG_SILENT_CONSOLE
	    fixup_silent_linux();
#endif
	    do_bootm_linux (flag, argc, argv, &images);
	    break;
#ifdef CONFIG_BOOTM_NETBSD
	case IH_OS_NETBSD:
	    do_bootm_netbsd (flag, argc, argv, &images);
	    break;
#endif
#ifdef CONFIG_LYNXKDI
	case IH_OS_LYNXOS:
	    do_bootm_lynxkdi (flag, argc, argv, &images);
	    break;
#endif
#ifdef CONFIG_BOOTM_RTEMS
	case IH_OS_RTEMS:
	    do_bootm_rtems (flag, argc, argv, &images);
	    break;
#endif
/*
#if defined(CONFIG_CMD_ELF)
	case IH_OS_VXWORKS:
	    do_bootm_vxworks (cmdtp, flag, argc, argv, &images);
	    break;

	case IH_OS_QNX:
	    do_bootm_qnxelf (cmdtp, flag, argc, argv, &images);
	    break;
#endif
*/
#ifdef CONFIG_ARTOS
	case IH_OS_ARTOS:
	    do_bootm_artos (cmdtp, flag, argc, argv, &images);
	    break;
#endif
	}

	show_boot_progress (-9);
#ifdef DEBUG
	puts ("\n## Control returned to monitor - resetting...\n");
	do_reset (cmdtp, flag, argc, argv);
#endif
	if (iflag)
		enable_interrupts();

	return 1;
}
Ejemplo n.º 27
0
void reserve_kdump_trampoline(void)
{
	lmb_reserve(0, KDUMP_RESERVE_LIMIT);
}
Ejemplo n.º 28
0
void __init setup_memory(void)
{
	int i;
	unsigned long map_size;
	u32 kernel_align_start, kernel_align_size;

	/* Find main memory where is the kernel */
	for (i = 0; i < lmb.memory.cnt; i++) {
		memory_start = (u32) lmb.memory.region[i].base;
		memory_end = (u32) lmb.memory.region[i].base
				+ (u32) lmb.memory.region[i].size;
		if ((memory_start <= (u32)_text) &&
					((u32)_text <= memory_end)) {
			memory_size = memory_end - memory_start;
			PAGE_OFFSET = memory_start;
			printk(KERN_INFO "%s: Main mem: 0x%x-0x%x, "
				"size 0x%08x\n", __func__, memory_start,
						memory_end, memory_size);
			break;
		}
	}

	if (!memory_start || !memory_end) {
		panic("%s: Missing memory setting 0x%08x-0x%08x\n",
			__func__, memory_start, memory_end);
	}

	/* reservation of region where is the kernel */
	kernel_align_start = PAGE_DOWN((u32)_text);
	/* ALIGN can be remove because _end in vmlinux.lds.S is align */
	kernel_align_size = PAGE_UP((u32)klimit) - kernel_align_start;
	lmb_reserve(kernel_align_start, kernel_align_size);
	printk(KERN_INFO "%s: kernel addr=0x%08x-0x%08x size=0x%08x\n",
		__func__, kernel_align_start, kernel_align_start
			+ kernel_align_size, kernel_align_size);

	/*
	 * Kernel:
	 * start: base phys address of kernel - page align
	 * end: base phys address of kernel - page align
	 *
	 * min_low_pfn - the first page (mm/bootmem.c - node_boot_start)
	 * max_low_pfn
	 * max_mapnr - the first unused page (mm/bootmem.c - node_low_pfn)
	 * num_physpages - number of all pages
	 */

	/* memory start is from the kernel end (aligned) to higher addr */
	min_low_pfn = memory_start >> PAGE_SHIFT; /* minimum for allocation */
	/* RAM is assumed contiguous */
	num_physpages = max_mapnr = memory_size >> PAGE_SHIFT;
	max_pfn = max_low_pfn = memory_end >> PAGE_SHIFT;

	printk(KERN_INFO "%s: max_mapnr: %#lx\n", __func__, max_mapnr);
	printk(KERN_INFO "%s: min_low_pfn: %#lx\n", __func__, min_low_pfn);
	printk(KERN_INFO "%s: max_low_pfn: %#lx\n", __func__, max_low_pfn);

	/*
	 * Find an area to use for the bootmem bitmap.
	 * We look for the first area which is at least
	 * 128kB in length (128kB is enough for a bitmap
	 * for 4GB of memory, using 4kB pages), plus 1 page
	 * (in case the address isn't page-aligned).
	 */
	map_size = init_bootmem_node(NODE_DATA(0), PFN_UP(TOPHYS((u32)_end)),
					min_low_pfn, max_low_pfn);

	lmb_reserve(PFN_UP(TOPHYS((u32)_end)) << PAGE_SHIFT, map_size);

	/* free bootmem is whole main memory */
	free_bootmem(memory_start, memory_size);

	/* reserve allocate blocks */
	for (i = 0; i < lmb.reserved.cnt; i++) {
		pr_debug("reserved %d - 0x%08x-0x%08x\n", i,
			(u32) lmb.reserved.region[i].base,
			(u32) lmb_size_bytes(&lmb.reserved, i));
		reserve_bootmem(lmb.reserved.region[i].base,
			lmb_size_bytes(&lmb.reserved, i) - 1, BOOTMEM_DEFAULT);
	}
	paging_init();
}
Ejemplo n.º 29
0
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	ulong		iflag;
	ulong		load_end = 0;
	int		ret;
	boot_os_fn	*boot_fn;

	/* relocate boot function table */
	if (!relocated) {
		int i;
		for (i = 0; i < ARRAY_SIZE(boot_os); i++)
			if (boot_os[i] != NULL)
				boot_os[i] += gd->reloc_off;
		relocated = 1;
	}

	/* determine if we have a sub command */
	if (argc > 1) {
		char *endp;

		simple_strtoul(argv[1], &endp, 16);
		/* endp pointing to NULL means that argv[1] was just a
		 * valid number, pass it along to the normal bootm processing
		 *
		 * If endp is ':' or '#' assume a FIT identifier so pass
		 * along for normal processing.
		 *
		 * Right now we assume the first arg should never be '-'
		 */
		if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
			return do_bootm_subcommand(cmdtp, flag, argc, argv);
	}

	if (bootm_start(cmdtp, flag, argc, argv))
		return 1;

	/*
	 * We have reached the point of no return: we are going to
	 * overwrite all exception vector code, so we cannot easily
	 * recover from any failures any more...
	 */
	iflag = disable_interrupts();

#if defined(CONFIG_CMD_USB)
	/*
	 * turn off USB to prevent the host controller from writing to the
	 * SDRAM while Linux is booting. This could happen (at least for OHCI
	 * controller), because the HCCA (Host Controller Communication Area)
	 * lies within the SDRAM and the host controller writes continously to
	 * this area (as busmaster!). The HccaFrameNumber is for example
	 * updated every 1 ms within the HCCA structure in SDRAM! For more
	 * details see the OpenHCI specification.
	 */
	usb_stop();
#endif

#ifdef CONFIG_AMIGAONEG3SE
	/*
	 * We've possible left the caches enabled during
	 * bios emulation, so turn them off again
	 */
	icache_disable();
	dcache_disable();
#endif

	ret = bootm_load_os(images.os, &load_end, 1);

	if (ret < 0) {
		if (ret == BOOTM_ERR_RESET)
			do_reset (cmdtp, flag, argc, argv);
		if (ret == BOOTM_ERR_OVERLAP) {
			if (images.legacy_hdr_valid) {
				if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
					puts ("WARNING: legacy format multi component "
						"image overwritten\n");
			} else {
				puts ("ERROR: new format image overwritten - "
					"must RESET the board to recover\n");
				show_boot_progress (-113);
				do_reset (cmdtp, flag, argc, argv);
			}
		}
		if (ret == BOOTM_ERR_UNIMPLEMENTED) {
			if (iflag)
				enable_interrupts();
			show_boot_progress (-7);
			return 1;
		}
	}

	lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));

	if (images.os.type == IH_TYPE_STANDALONE) {
		if (iflag)
			enable_interrupts();
		/* This may return when 'autostart' is 'no' */
		bootm_start_standalone(iflag, argc, argv);
		return 0;
	}

	show_boot_progress (8);

#ifdef CONFIG_SILENT_CONSOLE
	if (images.os.os == IH_OS_LINUX)
		fixup_silent_linux();
#endif

	boot_fn = boot_os[images.os.os];

	if (boot_fn == NULL) {
		if (iflag)
			enable_interrupts();
		printf ("ERROR: booting os '%s' (%d) is not supported\n",
			genimg_get_os_name(images.os.os), images.os.os);
		show_boot_progress (-8);
		return 1;
	}

	boot_fn(0, argc, argv, &images);

	show_boot_progress (-9);
#ifdef DEBUG
	puts ("\n## Control returned to monitor - resetting...\n");
#endif
	do_reset (cmdtp, flag, argc, argv);

	return 1;
}
Ejemplo n.º 30
0
/**
 * boot_ramdisk_high - relocate init ramdisk
 * @lmb: pointer to lmb handle, will be used for memory mgmt
 * @rd_data: ramdisk data start address
 * @rd_len: ramdisk data length
 * @initrd_start: pointer to a ulong variable, will hold final init ramdisk
 *      start address (after possible relocation)
 * @initrd_end: pointer to a ulong variable, will hold final init ramdisk
 *      end address (after possible relocation)
 *
 * boot_ramdisk_high() takes a relocation hint from "initrd_high" environment
 * variable and if requested ramdisk data is moved to a specified location.
 *
 * Initrd_start and initrd_end are set to final (after relocation) ramdisk
 * start/end addresses if ramdisk image start and len were provided,
 * otherwise set initrd_start and initrd_end set to zeros.
 *
 * returns:
 *      0 - success
 *     -1 - failure
 */
int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len,
		  ulong *initrd_start, ulong *initrd_end)
{
	char	*s;
	ulong	initrd_high;
	int	initrd_copy_to_ram = 1;

	if ((s = getenv("initrd_high")) != NULL) {
		/* a value of "no" or a similar string will act like 0,
		 * turning the "load high" feature off. This is intentional.
		 */
		initrd_high = simple_strtoul(s, NULL, 16);
		if (initrd_high == ~0)
			initrd_copy_to_ram = 0;
	} else {
		/* not set, no restrictions to load high */
		initrd_high = ~0;
	}


#ifdef CONFIG_LOGBUFFER
	/* Prevent initrd from overwriting logbuffer */
	lmb_reserve(lmb, logbuffer_base() - LOGBUFF_OVERHEAD, LOGBUFF_RESERVE);
#endif

	debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n",
			initrd_high, initrd_copy_to_ram);

	if (rd_data) {
		if (!initrd_copy_to_ram) {	/* zero-copy ramdisk support */
			debug("   in-place initrd\n");
			*initrd_start = rd_data;
			*initrd_end = rd_data + rd_len;
			lmb_reserve(lmb, rd_data, rd_len);
		} else {
			if (initrd_high)
				*initrd_start = (ulong)lmb_alloc_base(lmb,
						rd_len, 0x1000, initrd_high);
			else
				*initrd_start = (ulong)lmb_alloc(lmb, rd_len,
								 0x1000);

			if (*initrd_start == 0) {
				puts("ramdisk - allocation error\n");
				goto error;
			}
			bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK);

			*initrd_end = *initrd_start + rd_len;
			printf("   Loading Ramdisk to %08lx, end %08lx ... ",
					*initrd_start, *initrd_end);

			memmove_wd((void *)*initrd_start,
					(void *)rd_data, rd_len, CHUNKSZ);

#ifdef CONFIG_MP
			/*
			 * Ensure the image is flushed to memory to handle
			 * AMP boot scenarios in which we might not be
			 * HW cache coherent
			 */
			flush_cache((unsigned long)*initrd_start, rd_len);
#endif
			puts("OK\n");
		}
	} else {
		*initrd_start = 0;
		*initrd_end = 0;
	}
	debug("   ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n",
			*initrd_start, *initrd_end);

	return 0;

error:
	return -1;
}