Пример #1
0
struct bi_record *
load_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
{
	timebase_period_ns = 3;
	mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR);		  /* reset MAL */
	while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* wait for reset */
	*(volatile unsigned long *)PPC44x_EMAC0_MR0 = 0x20000000; /* reset EMAC */
	eieio();

	return decompress_kernel(load_addr, num_words, cksum);
}
Пример #2
0
Файл: misc.c Проект: 274914765/C
struct bi_record *
decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
{
#ifdef INTERACTIVE_CONSOLE
    int timer = 0;
    char ch;
#endif
    char *cp;
    struct bi_record *rec;
    unsigned long initrd_loc = 0, TotalMemory = 0;

#if defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_MPSC_CONSOLE)
    com_port = serial_init(0, NULL);
#endif

#if defined(PPC4xx_EMAC0_MR0)
    /* Reset MAL */
    mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR);
    /* Wait for reset */
    while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {};
    /* Reset EMAC */
    *(volatile unsigned long *)PPC4xx_EMAC0_MR0 = 0x20000000;
    __asm__ __volatile__("eieio");
#endif

    /*
     * Call get_mem_size(), which is memory controller dependent,
     * and we must have the correct file linked in here.
     */
    TotalMemory = get_mem_size();

    /* assume the chunk below 8M is free */
    end_avail = (char *)0x00800000;

    /*
     * Reveal where we were loaded at and where we
     * were relocated to.
     */
    puts("loaded at:     "); puthex(load_addr);
    puts(" "); puthex((unsigned long)(load_addr + (4*num_words)));
    puts("\n");
    if ( (unsigned long)load_addr != (unsigned long)&start )
    {
        puts("relocated to:  "); puthex((unsigned long)&start);
        puts(" ");
        puthex((unsigned long)((unsigned long)&start + (4*num_words)));
        puts("\n");
    }

    /*
     * We link ourself to 0x00800000.  When we run, we relocate
     * ourselves there.  So we just need __image_begin for the
     * start. -- Tom
     */
    zimage_start = (char *)(unsigned long)(&__image_begin);
    zimage_size = (unsigned long)(&__image_end) -
            (unsigned long)(&__image_begin);

    initrd_size = (unsigned long)(&__ramdisk_end) -
        (unsigned long)(&__ramdisk_begin);

    /*
     * The zImage and initrd will be between start and _end, so they've
     * already been moved once.  We're good to go now. -- Tom
     */
    avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
    puts("zimage at:     "); puthex((unsigned long)zimage_start);
    puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
    puts("\n");

    if ( initrd_size ) {
        puts("initrd at:     ");
        puthex((unsigned long)(&__ramdisk_begin));
        puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
    }

#ifndef CONFIG_40x /* don't overwrite the 40x image located at 0x00400000! */
    avail_ram = (char *)0x00400000;
#endif
    end_avail = (char *)0x00800000;
    puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
    puthex((unsigned long)end_avail); puts("\n");

    if (keyb_present)
        CRT_tstc();  /* Forces keyboard to be initialized */

    /* Display standard Linux/PPC boot prompt for kernel args */
    puts("\nLinux/PPC load: ");
    cp = cmd_line;
    memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
    while ( *cp ) putc(*cp++);

#ifdef INTERACTIVE_CONSOLE
    /*
     * If they have a console, allow them to edit the command line.
     * Otherwise, don't bother wasting the five seconds.
     */
    while (timer++ < 5*1000) {
        if (tstc()) {
            while ((ch = getc()) != '\n' && ch != '\r') {
                /* Test for backspace/delete */
                if (ch == '\b' || ch == '\177') {
                    if (cp != cmd_line) {
                        cp--;
                        puts("\b \b");
                    }
                /* Test for ^x/^u (and wipe the line) */
                } else if (ch == '\030' || ch == '\025') {
                    while (cp != cmd_line) {
                        cp--;
                        puts("\b \b");
                    }
                } else {
                    *cp++ = ch;
                    putc(ch);
                }
            }
            break;  /* Exit 'timer' loop */
        }
        udelay(1000);  /* 1 msec */
    }
    *cp = 0;
#endif
    puts("\n");

    puts("Uncompressing Linux...");
    gunzip(NULL, 0x400000, zimage_start, &zimage_size);
    puts("done.\n");

    /* get the bi_rec address */
    rec = bootinfo_addr(zimage_size);

    /* We need to make sure that the initrd and bi_recs do not
     * overlap. */
    if ( initrd_size ) {
        unsigned long rec_loc = (unsigned long) rec;
        initrd_loc = (unsigned long)(&__ramdisk_begin);
        /* If the bi_recs are in the middle of the current
         * initrd, move the initrd to the next MB
         * boundary. */
        if ((rec_loc > initrd_loc) &&
                ((initrd_loc + initrd_size) > rec_loc)) {
            initrd_loc = _ALIGN((unsigned long)(zimage_size)
                    + (2 << 20) - 1, (2 << 20));
             memmove((void *)initrd_loc, &__ramdisk_begin,
                 initrd_size);
                 puts("initrd moved:  "); puthex(initrd_loc);
             puts(" "); puthex(initrd_loc + initrd_size);
             puts("\n");
        }
    }

    bootinfo_init(rec);
    if ( TotalMemory )
        bootinfo_append(BI_MEMSIZE, sizeof(int), (void*)&TotalMemory);

    bootinfo_append(BI_CMD_LINE, strlen(cmd_line)+1, (void*)cmd_line);

    /* add a bi_rec for the initrd if it exists */
    if (initrd_size) {
        unsigned long initrd[2];

        initrd[0] = initrd_loc;
        initrd[1] = initrd_size;

        bootinfo_append(BI_INITRD, sizeof(initrd), &initrd);
    }
    puts("Now booting the kernel\n");
    serial_close(com_port);

    return rec;
}