OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [powerpc/] [boot/] [main.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * Copyright (C) Paul Mackerras 1997.
3
 *
4
 * Updates for PPC64 by Todd Inglett, Dave Engebretsen & Peter Bergner.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version
9
 * 2 of the License, or (at your option) any later version.
10
 */
11
#include <stdarg.h>
12
#include <stddef.h>
13
#include "elf.h"
14
#include "page.h"
15
#include "string.h"
16
#include "stdio.h"
17
#include "ops.h"
18
#include "gunzip_util.h"
19
#include "flatdevtree.h"
20
#include "reg.h"
21
 
22
static struct gunzip_state gzstate;
23
 
24
struct addr_range {
25
        void *addr;
26
        unsigned long size;
27
};
28
 
29
#undef DEBUG
30
 
31
static struct addr_range prep_kernel(void)
32
{
33
        char elfheader[256];
34
        void *vmlinuz_addr = _vmlinux_start;
35
        unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start;
36
        void *addr = 0;
37
        struct elf_info ei;
38
        int len;
39
 
40
        /* gunzip the ELF header of the kernel */
41
        gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size);
42
        gunzip_exactly(&gzstate, elfheader, sizeof(elfheader));
43
 
44
        if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
45
                fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
46
 
47
        if (platform_ops.image_hdr)
48
                platform_ops.image_hdr(elfheader);
49
 
50
        /* We need to alloc the memsize: gzip will expand the kernel
51
         * text/data, then possible rubbish we don't care about. But
52
         * the kernel bss must be claimed (it will be zero'd by the
53
         * kernel itself)
54
         */
55
        printf("Allocating 0x%lx bytes for kernel ...\n\r", ei.memsize);
56
 
57
        if (platform_ops.vmlinux_alloc) {
58
                addr = platform_ops.vmlinux_alloc(ei.memsize);
59
        } else {
60
                if ((unsigned long)_start < ei.memsize)
61
                        fatal("Insufficient memory for kernel at address 0!"
62
                               " (_start=%p)\n\r", _start);
63
        }
64
 
65
        /* Finally, gunzip the kernel */
66
        printf("gunzipping (0x%p <- 0x%p:0x%p)...", addr,
67
               vmlinuz_addr, vmlinuz_addr+vmlinuz_size);
68
        /* discard up to the actual load data */
69
        gunzip_discard(&gzstate, ei.elfoffset - sizeof(elfheader));
70
        len = gunzip_finish(&gzstate, addr, ei.loadsize);
71
        if (len != ei.loadsize)
72
                fatal("ran out of data!  only got 0x%x of 0x%lx bytes.\n\r",
73
                                len, ei.loadsize);
74
        printf("done 0x%x bytes\n\r", len);
75
 
76
        flush_cache(addr, ei.loadsize);
77
 
78
        return (struct addr_range){addr, ei.memsize};
79
}
80
 
81
static struct addr_range prep_initrd(struct addr_range vmlinux, void *chosen,
82
                                     unsigned long initrd_addr,
83
                                     unsigned long initrd_size)
84
{
85
        /* If we have an image attached to us, it overrides anything
86
         * supplied by the loader. */
87
        if (_initrd_end > _initrd_start) {
88
                printf("Attached initrd image at 0x%p-0x%p\n\r",
89
                       _initrd_start, _initrd_end);
90
                initrd_addr = (unsigned long)_initrd_start;
91
                initrd_size = _initrd_end - _initrd_start;
92
        } else if (initrd_size > 0) {
93
                printf("Using loader supplied ramdisk at 0x%lx-0x%lx\n\r",
94
                       initrd_addr, initrd_addr + initrd_size);
95
        }
96
 
97
        /* If there's no initrd at all, we're done */
98
        if (! initrd_size)
99
                return (struct addr_range){0, 0};
100
 
101
        /*
102
         * If the initrd is too low it will be clobbered when the
103
         * kernel relocates to its final location.  In this case,
104
         * allocate a safer place and move it.
105
         */
106
        if (initrd_addr < vmlinux.size) {
107
                void *old_addr = (void *)initrd_addr;
108
 
109
                printf("Allocating 0x%lx bytes for initrd ...\n\r",
110
                       initrd_size);
111
                initrd_addr = (unsigned long)malloc(initrd_size);
112
                if (! initrd_addr)
113
                        fatal("Can't allocate memory for initial "
114
                               "ramdisk !\n\r");
115
                printf("Relocating initrd 0x%lx <- 0x%p (0x%lx bytes)\n\r",
116
                       initrd_addr, old_addr, initrd_size);
117
                memmove((void *)initrd_addr, old_addr, initrd_size);
118
        }
119
 
120
        printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd_addr));
121
 
122
        /* Tell the kernel initrd address via device tree */
123
        setprop_val(chosen, "linux,initrd-start", (u32)(initrd_addr));
124
        setprop_val(chosen, "linux,initrd-end", (u32)(initrd_addr+initrd_size));
125
 
126
        return (struct addr_range){(void *)initrd_addr, initrd_size};
127
}
128
 
129
/* A buffer that may be edited by tools operating on a zImage binary so as to
130
 * edit the command line passed to vmlinux (by setting /chosen/bootargs).
131
 * The buffer is put in it's own section so that tools may locate it easier.
132
 */
133
static char cmdline[COMMAND_LINE_SIZE]
134
        __attribute__((__section__("__builtin_cmdline")));
135
 
136
static void prep_cmdline(void *chosen)
137
{
138
        if (cmdline[0] == '\0')
139
                getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
140
 
141
        printf("\n\rLinux/PowerPC load: %s", cmdline);
142
        /* If possible, edit the command line */
143
        if (console_ops.edit_cmdline)
144
                console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
145
        printf("\n\r");
146
 
147
        /* Put the command line back into the devtree for the kernel */
148
        setprop_str(chosen, "bootargs", cmdline);
149
}
150
 
151
struct platform_ops platform_ops;
152
struct dt_ops dt_ops;
153
struct console_ops console_ops;
154
struct loader_info loader_info;
155
 
156
void start(void)
157
{
158
        struct addr_range vmlinux, initrd;
159
        kernel_entry_t kentry;
160
        unsigned long ft_addr = 0;
161
        void *chosen;
162
 
163
        /* Do this first, because malloc() could clobber the loader's
164
         * command line.  Only use the loader command line if a
165
         * built-in command line wasn't set by an external tool */
166
        if ((loader_info.cmdline_len > 0) && (cmdline[0] == '\0'))
167
                memmove(cmdline, loader_info.cmdline,
168
                        min(loader_info.cmdline_len, COMMAND_LINE_SIZE-1));
169
 
170
        if (console_ops.open && (console_ops.open() < 0))
171
                exit();
172
        if (platform_ops.fixups)
173
                platform_ops.fixups();
174
 
175
        printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
176
               _start, get_sp());
177
 
178
        /* Ensure that the device tree has a /chosen node */
179
        chosen = finddevice("/chosen");
180
        if (!chosen)
181
                chosen = create_node(NULL, "chosen");
182
 
183
        vmlinux = prep_kernel();
184
        initrd = prep_initrd(vmlinux, chosen,
185
                             loader_info.initrd_addr, loader_info.initrd_size);
186
        prep_cmdline(chosen);
187
 
188
        printf("Finalizing device tree...");
189
        if (dt_ops.finalize)
190
                ft_addr = dt_ops.finalize();
191
        if (ft_addr)
192
                printf(" flat tree at 0x%lx\n\r", ft_addr);
193
        else
194
                printf(" using OF tree (promptr=%p)\n\r", loader_info.promptr);
195
 
196
        if (console_ops.close)
197
                console_ops.close();
198
 
199
        kentry = (kernel_entry_t) vmlinux.addr;
200
        if (ft_addr)
201
                kentry(ft_addr, 0, NULL);
202
        else
203
                kentry((unsigned long)initrd.addr, initrd.size,
204
                       loader_info.promptr);
205
 
206
        /* console closed so printf in fatal below may not work */
207
        fatal("Error: Linux kernel returned to zImage boot wrapper!\n\r");
208
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.