~ubuntu-branches/ubuntu/saucy/u-boot/saucy

« back to all changes in this revision

Viewing changes to arch/x86/lib/zimage.c

  • Committer: Package Import Robot
  • Author(s): Clint Adams
  • Date: 2012-05-01 18:07:19 UTC
  • mfrom: (16.1.23 sid)
  • Revision ID: package-import@ubuntu.com-20120501180719-rjntk3287im4a0ns
Tags: 2012.04.01-1
* New upstream version.
  - Update mipsel-native-endianness.diff.
  - Update no-error-on-set-but-unused-variables.diff (partially merged).
  - Drop kirkwood_spi-irq_mask.diff (merged).
  - Drop kirkwood-disable-l2c.diff (merged).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
 
2
 * Copyright (c) 2011 The Chromium OS Authors.
2
3
 * (C) Copyright 2002
3
4
 * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
4
5
 *
51
52
 
52
53
#define COMMAND_LINE_SIZE       2048
53
54
 
 
55
unsigned generic_install_e820_map(unsigned max_entries,
 
56
                                  struct e820entry *entries)
 
57
{
 
58
        return 0;
 
59
}
 
60
 
 
61
unsigned install_e820_map(unsigned max_entries,
 
62
                          struct e820entry *entries)
 
63
        __attribute__((weak, alias("generic_install_e820_map")));
 
64
 
54
65
static void build_command_line(char *command_line, int auto_boot)
55
66
{
56
67
        char *env_command_line;
78
89
        printf("Kernel command line: \"%s\"\n", command_line);
79
90
}
80
91
 
81
 
void *load_zimage(char *image, unsigned long kernel_size,
82
 
                  unsigned long initrd_addr, unsigned long initrd_size,
83
 
                  int auto_boot)
 
92
static int kernel_magic_ok(struct setup_header *hdr)
84
93
{
85
 
        void *setup_base;
86
 
        int setup_size;
87
 
        int bootproto;
88
 
        int big_image;
89
 
        void *load_address;
90
 
        struct setup_header *hdr;
91
 
 
92
 
        hdr = (struct setup_header *)(image + SETUP_SECTS_OFF);
93
 
 
94
 
        /* base address for real-mode segment */
95
 
        setup_base = (void *)DEFAULT_SETUP_BASE;
96
 
 
97
94
        if (KERNEL_MAGIC != hdr->boot_flag) {
98
 
                printf("Error: Invalid Boot Flag (found 0x%04x, expected 0x%04x)\n",
99
 
                       hdr->boot_flag, KERNEL_MAGIC);
 
95
                printf("Error: Invalid Boot Flag "
 
96
                        "(found 0x%04x, expected 0x%04x)\n",
 
97
                        hdr->boot_flag, KERNEL_MAGIC);
100
98
                return 0;
101
99
        } else {
102
100
                printf("Valid Boot Flag\n");
 
101
                return 1;
103
102
        }
 
103
}
104
104
 
105
 
        /* determine boot protocol version */
106
 
        if (KERNEL_V2_MAGIC == hdr->header) {
 
105
static int get_boot_protocol(struct setup_header *hdr)
 
106
{
 
107
        if (hdr->header == KERNEL_V2_MAGIC) {
107
108
                printf("Magic signature found\n");
108
 
 
109
 
                bootproto = hdr->version;
 
109
                return hdr->version;
110
110
        } else {
111
111
                /* Very old kernel */
112
112
                printf("Magic signature not found\n");
113
 
                bootproto = 0x0100;
 
113
                return 0x0100;
114
114
        }
 
115
}
 
116
 
 
117
struct boot_params *load_zimage(char *image, unsigned long kernel_size,
 
118
                                void **load_address)
 
119
{
 
120
        struct boot_params *setup_base;
 
121
        int setup_size;
 
122
        int bootproto;
 
123
        int big_image;
 
124
 
 
125
        struct boot_params *params = (struct boot_params *)image;
 
126
        struct setup_header *hdr = &params->hdr;
 
127
 
 
128
        /* base address for real-mode segment */
 
129
        setup_base = (struct boot_params *)DEFAULT_SETUP_BASE;
 
130
 
 
131
        if (!kernel_magic_ok(hdr))
 
132
                return 0;
115
133
 
116
134
        /* determine size of setup */
117
135
        if (0 == hdr->setup_sects) {
126
144
        if (setup_size > SETUP_MAX_SIZE)
127
145
                printf("Error: Setup is too large (%d bytes)\n", setup_size);
128
146
 
 
147
        /* determine boot protocol version */
 
148
        bootproto = get_boot_protocol(hdr);
 
149
 
 
150
        printf("Using boot protocol version %x.%02x\n",
 
151
               (bootproto & 0xff00) >> 8, bootproto & 0xff);
 
152
 
 
153
        if (bootproto >= 0x0200) {
 
154
                if (hdr->setup_sects >= 15) {
 
155
                        printf("Linux kernel version %s\n",
 
156
                                (char *)params +
 
157
                                hdr->kernel_version + 0x200);
 
158
                } else {
 
159
                        printf("Setup Sectors < 15 - "
 
160
                                "Cannot print kernel version.\n");
 
161
                }
 
162
        }
 
163
 
129
164
        /* Determine image type */
130
165
        big_image = (bootproto >= 0x0200) &&
131
166
                    (hdr->loadflags & BIG_KERNEL_FLAG);
132
167
 
133
168
        /* Determine load address */
134
 
        load_address = (void *)(big_image ?
135
 
                                BZIMAGE_LOAD_ADDR :
136
 
                                ZIMAGE_LOAD_ADDR);
 
169
        if (big_image)
 
170
                *load_address = (void *)BZIMAGE_LOAD_ADDR;
 
171
        else
 
172
                *load_address = (void *)ZIMAGE_LOAD_ADDR;
137
173
 
 
174
#if defined CONFIG_ZBOOT_32
 
175
        printf("Building boot_params at 0x%8.8lx\n", (ulong)setup_base);
 
176
        memset(setup_base, 0, sizeof(*setup_base));
 
177
        setup_base->hdr = params->hdr;
 
178
#else
138
179
        /* load setup */
139
180
        printf("Moving Real-Mode Code to 0x%8.8lx (%d bytes)\n",
140
181
               (ulong)setup_base, setup_size);
141
182
        memmove(setup_base, image, setup_size);
 
183
#endif
142
184
 
143
 
        printf("Using boot protocol version %x.%02x\n",
144
 
               (bootproto & 0xff00) >> 8, bootproto & 0xff);
 
185
        if (bootproto >= 0x0204)
 
186
                kernel_size = hdr->syssize * 16;
 
187
        else
 
188
                kernel_size -= setup_size;
145
189
 
146
190
        if (bootproto == 0x0100) {
147
 
                *(u16 *)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC;
148
 
                *(u16 *)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET;
149
 
 
150
191
                /*
151
192
                 * A very old kernel MUST have its real-mode code
152
193
                 * loaded at 0x90000
157
198
 
158
199
                        /* Copy the command line */
159
200
                        memmove((void *)0x99000,
160
 
                                setup_base + COMMAND_LINE_OFFSET,
 
201
                                (u8 *)setup_base + COMMAND_LINE_OFFSET,
161
202
                                COMMAND_LINE_SIZE);
162
203
 
163
204
                         /* Relocated */
164
 
                        setup_base = (void *)0x90000;
 
205
                        setup_base = (struct boot_params *)0x90000;
165
206
                }
166
207
 
167
208
                /* It is recommended to clear memory up to the 32K mark */
168
 
                memset((void *)0x90000 + setup_size, 0,
169
 
                       SETUP_MAX_SIZE-setup_size);
170
 
        }
171
 
 
172
 
        /* We are now setting up the real-mode version of the header */
173
 
        hdr = (struct setup_header *)(setup_base + SETUP_SECTS_OFF);
174
 
 
 
209
                memset((u8 *)0x90000 + setup_size, 0,
 
210
                       SETUP_MAX_SIZE - setup_size);
 
211
        }
 
212
 
 
213
        if (big_image) {
 
214
                if (kernel_size > BZIMAGE_MAX_SIZE) {
 
215
                        printf("Error: bzImage kernel too big! "
 
216
                                "(size: %ld, max: %d)\n",
 
217
                                kernel_size, BZIMAGE_MAX_SIZE);
 
218
                        return 0;
 
219
                }
 
220
        } else if ((kernel_size) > ZIMAGE_MAX_SIZE) {
 
221
                printf("Error: zImage kernel too big! (size: %ld, max: %d)\n",
 
222
                       kernel_size, ZIMAGE_MAX_SIZE);
 
223
                return 0;
 
224
        }
 
225
 
 
226
        printf("Loading %s at address %p (%ld bytes)\n",
 
227
                big_image ? "bzImage" : "zImage", *load_address, kernel_size);
 
228
 
 
229
        memmove(*load_address, image + setup_size, kernel_size);
 
230
 
 
231
        return setup_base;
 
232
}
 
233
 
 
234
int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
 
235
                 unsigned long initrd_addr, unsigned long initrd_size)
 
236
{
 
237
        struct setup_header *hdr = &setup_base->hdr;
 
238
        int bootproto = get_boot_protocol(hdr);
 
239
 
 
240
#if defined CONFIG_ZBOOT_32
 
241
        setup_base->e820_entries = install_e820_map(
 
242
                ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
 
243
#endif
 
244
 
 
245
        if (bootproto == 0x0100) {
 
246
                setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC;
 
247
                setup_base->screen_info.cl_offset = COMMAND_LINE_OFFSET;
 
248
        }
175
249
        if (bootproto >= 0x0200) {
176
250
                hdr->type_of_loader = 8;
177
251
 
178
 
                if (hdr->setup_sects >= 15)
179
 
                        printf("Linux kernel version %s\n",
180
 
                               (char *)(setup_base +
181
 
                                        (hdr->kernel_version + 0x200)));
182
 
                else
183
 
                        printf("Setup Sectors < 15 - Cannot print kernel version.\n");
184
 
 
185
252
                if (initrd_addr) {
186
 
                        printf("Initial RAM disk at linear address 0x%08lx, size %ld bytes\n",
 
253
                        printf("Initial RAM disk at linear address "
 
254
                               "0x%08lx, size %ld bytes\n",
187
255
                               initrd_addr, initrd_size);
188
256
 
189
257
                        hdr->ramdisk_image = initrd_addr;
197
265
        }
198
266
 
199
267
        if (bootproto >= 0x0202) {
200
 
                hdr->cmd_line_ptr = (u32)setup_base + COMMAND_LINE_OFFSET;
 
268
                hdr->cmd_line_ptr = (uintptr_t)cmd_line;
201
269
        } else if (bootproto >= 0x0200) {
202
 
 
203
 
                *(u16 *)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC;
204
 
                *(u16 *)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET;
 
270
                setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC;
 
271
                setup_base->screen_info.cl_offset =
 
272
                        (uintptr_t)cmd_line - (uintptr_t)setup_base;
205
273
 
206
274
                hdr->setup_move_size = 0x9100;
207
275
        }
208
276
 
209
 
        if (bootproto >= 0x0204)
210
 
                kernel_size = hdr->syssize * 16;
211
 
        else
212
 
                kernel_size -= setup_size;
213
 
 
214
 
 
215
 
        if (big_image) {
216
 
                if ((kernel_size) > BZIMAGE_MAX_SIZE) {
217
 
                        printf("Error: bzImage kernel too big! (size: %ld, max: %d)\n",
218
 
                               kernel_size, BZIMAGE_MAX_SIZE);
219
 
                        return 0;
220
 
                }
221
 
 
222
 
        } else if ((kernel_size) > ZIMAGE_MAX_SIZE) {
223
 
                printf("Error: zImage kernel too big! (size: %ld, max: %d)\n",
224
 
                       kernel_size, ZIMAGE_MAX_SIZE);
225
 
                return 0;
226
 
        }
227
 
 
228
277
        /* build command line at COMMAND_LINE_OFFSET */
229
 
        build_command_line(setup_base + COMMAND_LINE_OFFSET, auto_boot);
230
 
 
231
 
        printf("Loading %czImage at address 0x%08x (%ld bytes)\n",
232
 
               big_image ? 'b' : ' ', (u32)load_address, kernel_size);
233
 
 
234
 
 
235
 
        memmove(load_address, image + setup_size, kernel_size);
236
 
 
237
 
        /* ready for booting */
238
 
        return setup_base;
 
278
        build_command_line(cmd_line, auto_boot);
 
279
        return 0;
239
280
}
240
281
 
241
 
void boot_zimage(void *setup_base)
 
282
void boot_zimage(void *setup_base, void *load_address)
242
283
{
 
284
        printf("\nStarting kernel ...\n\n");
 
285
 
 
286
#if defined CONFIG_ZBOOT_32
 
287
        /*
 
288
         * Set %ebx, %ebp, and %edi to 0, %esi to point to the boot_params
 
289
         * structure, and then jump to the kernel. We assume that %cs is
 
290
         * 0x10, 4GB flat, and read/execute, and the data segments are 0x18,
 
291
         * 4GB flat, and read/write. U-boot is setting them up that way for
 
292
         * itself in arch/i386/cpu/cpu.c.
 
293
         */
 
294
        __asm__ __volatile__ (
 
295
        "movl $0, %%ebp         \n"
 
296
        "cli                    \n"
 
297
        "jmp %[kernel_entry]    \n"
 
298
        :: [kernel_entry]"a"(load_address),
 
299
           [boot_params] "S"(setup_base),
 
300
           "b"(0), "D"(0)
 
301
        :  "%ebp"
 
302
        );
 
303
#else
243
304
        struct pt_regs regs;
244
305
 
245
306
        memset(&regs, 0, sizeof(struct pt_regs));
248
309
        regs.xss = regs.xds;
249
310
        regs.esp = 0x9000;
250
311
        regs.eflags = 0;
251
 
        enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, &regs,
252
 
                       &regs);
 
312
        enter_realmode(((u32)setup_base + SETUP_START_OFFSET) >> 4, 0,
 
313
                       &regs, &regs);
 
314
#endif
 
315
}
 
316
 
 
317
void setup_pcat_compatibility(void)
 
318
        __attribute__((weak, alias("__setup_pcat_compatibility")));
 
319
 
 
320
void __setup_pcat_compatibility(void)
 
321
{
253
322
}
254
323
 
255
324
int do_zboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
256
325
{
257
 
        void *base_ptr;
 
326
        struct boot_params *base_ptr;
258
327
        void *bzImage_addr = NULL;
 
328
        void *load_address;
259
329
        char *s;
260
330
        ulong bzImage_size = 0;
 
331
        ulong initrd_addr = 0;
 
332
        ulong initrd_size = 0;
261
333
 
262
334
        disable_interrupts();
263
335
 
264
336
        /* Setup board for maximum PC/AT Compatibility */
265
337
        setup_pcat_compatibility();
266
338
 
267
 
        if (argc >= 2)
 
339
        if (argc >= 2) {
268
340
                /* argv[1] holds the address of the bzImage */
269
341
                s = argv[1];
270
 
        else
 
342
        } else {
271
343
                s = getenv("fileaddr");
 
344
        }
272
345
 
273
346
        if (s)
274
347
                bzImage_addr = (void *)simple_strtoul(s, NULL, 16);
275
348
 
276
 
        if (argc >= 3)
 
349
        if (argc >= 3) {
277
350
                /* argv[2] holds the size of the bzImage */
278
351
                bzImage_size = simple_strtoul(argv[2], NULL, 16);
279
 
 
280
 
        /* Lets look for*/
281
 
        base_ptr = load_zimage(bzImage_addr, bzImage_size, 0, 0, 0);
 
352
        }
 
353
 
 
354
        if (argc >= 4)
 
355
                initrd_addr = simple_strtoul(argv[3], NULL, 16);
 
356
        if (argc >= 5)
 
357
                initrd_size = simple_strtoul(argv[4], NULL, 16);
 
358
 
 
359
        /* Lets look for */
 
360
        base_ptr = load_zimage(bzImage_addr, bzImage_size, &load_address);
282
361
 
283
362
        if (!base_ptr) {
284
363
                printf("## Kernel loading failed ...\n");
285
 
        } else {
286
 
                printf("## Transferring control to Linux (at address %08x) ...\n",
287
 
                        (u32)base_ptr);
288
 
 
289
 
                /* we assume that the kernel is in place */
290
 
                printf("\nStarting kernel ...\n\n");
291
 
 
292
 
                boot_zimage(base_ptr);
293
 
                /* does not return */
294
 
        }
 
364
                return -1;
 
365
        }
 
366
        if (setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET,
 
367
                        0, initrd_addr, initrd_size)) {
 
368
                printf("Setting up boot parameters failed ...\n");
 
369
                return -1;
 
370
        }
 
371
 
 
372
        printf("## Transferring control to Linux "
 
373
               "(at address %08x) ...\n",
 
374
               (u32)base_ptr);
 
375
 
 
376
        /* we assume that the kernel is in place */
 
377
        boot_zimage(base_ptr, load_address);
 
378
        /* does not return */
295
379
 
296
380
        return -1;
297
381
}
298
382
 
299
383
U_BOOT_CMD(
300
 
        zboot, 2, 0,    do_zboot,
 
384
        zboot, 5, 0,    do_zboot,
301
385
        "Boot bzImage",
302
 
        ""
 
386
        "[addr] [size] [initrd addr] [initrd size]\n"
 
387
        "      addr -        The optional starting address of the bzimage.\n"
 
388
        "                    If not set it defaults to the environment\n"
 
389
        "                    variable \"fileaddr\".\n"
 
390
        "      size -        The optional size of the bzimage. Defaults to\n"
 
391
        "                    zero.\n"
 
392
        "      initrd addr - The address of the initrd image to use, if any.\n"
 
393
        "      initrd size - The size of the initrd image to use, if any.\n"
303
394
);