~ubuntu-branches/ubuntu/hardy/silo/hardy-updates

« back to all changes in this revision

Viewing changes to second/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2007-10-25 09:28:08 UTC
  • mfrom: (15.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071025092808-1yhj12t7s4zqsfu5
Tags: 1.4.13a+git20070930-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Build with -fno-stack-protector.
  - Change silo.postinst to automatically update the boot block without
    invoking siloconfig and keep asking questions on upgrades.
  - Convert silo.conf to use /dev/disk/by-uuid.
  - Ubuntu maintainer foobar.
  - Fix debian/rules call to dh_installdocs.
  - Drop the requirement of gcc-4.1 and start using default gcc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Second stage boot loader
 
2
   
 
3
   Coyright (C) 1996 Pete A. Zaitcev
 
4
                 1996 Maurizio Plaza
 
5
                 1996 David S. Miller
 
6
                 1996 Miguel de Icaza
 
7
                 1996,1997,1998,1999 Jakub Jelinek
 
8
                 2001 Ben Collins
 
9
   
 
10
   This program is free software; you can redistribute it and/or modify
 
11
   it under the terms of the GNU General Public License as published by
 
12
   the Free Software Foundation; either version 2 of the License, or
 
13
   (at your option) any later version.
 
14
   
 
15
   This program is distributed in the hope that it will be useful,
 
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
   GNU General Public License for more details.
 
19
 
 
20
   You should have received a copy of the GNU General Public License
 
21
   along with this program; if not, write to the Free Software
 
22
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
 
23
   USA.  */
 
24
 
 
25
/* TODO: This file is a good candidate for rewrite from scratch.  */
 
26
 
 
27
#include <silo.h>
 
28
#include <asm/page.h>
 
29
#include <linux/elf.h>
 
30
#include <stringops.h>
 
31
 
 
32
#ifndef NULL
 
33
#define NULL (void *)0
 
34
#endif
 
35
 
 
36
 
 
37
struct HdrS_struct {
 
38
        char magic[4];
 
39
        unsigned int linux_ver;
 
40
        unsigned short ver;
 
41
        unsigned short root_flags;
 
42
        unsigned short root_dev;
 
43
        unsigned short ram_flags;
 
44
        unsigned int ramdisk_image;
 
45
        unsigned int ramdisk_size;
 
46
        /* 0x201 */
 
47
        unsigned int reboot_cmd_ptr_high;
 
48
        unsigned int reboot_cmd_ptr_low;
 
49
        /* 0x202 */
 
50
        unsigned int bootstr_info_ptr_high;
 
51
        unsigned int bootstr_info_ptr_low;
 
52
        /* 0x301 */
 
53
        unsigned long long ramdisk_image64;
 
54
};
 
55
 
 
56
/* This has to be first initialized variable in main.c */
 
57
 
 
58
extern char silo_conf[256];
 
59
extern unsigned char silo_conf_part, silo_conf_parts[32], raid_dsk_number;
 
60
 
 
61
int useconf = 0;
 
62
enum {
 
63
    CMD_BOOT,
 
64
    CMD_CAT,
 
65
    CMD_LS
 
66
} load_cmd;
 
67
enum arch architecture;
 
68
static int timer_status = 0;
 
69
static char *initrd_start;
 
70
static int initrd_size;
 
71
static int initrd_defpart;
 
72
static char *initrd_defdevice;
 
73
static char *initrd_string;
 
74
static int initrd_prompt;
 
75
static int pause_after;
 
76
static char *pause_message = "Press ENTER to continue.";
 
77
static int show_arguments = 0;
 
78
static char given_bootargs [512];
 
79
static char my_bootargs [512];
 
80
static int given_bootargs_by_user = 0;
 
81
static char sol_params [512];
 
82
static int fill_reboot_cmd = 0;
 
83
static char other_device [512];
 
84
static int reboot = 0;
 
85
static int floppyswap = 0;
 
86
int tab_ambiguous = 0;
 
87
int other_part = -1;
 
88
int solaris = 0;
 
89
int other = 0;
 
90
char *password = 0;
 
91
int initrd_can_do_64bit_phys = 0;
 
92
 
 
93
static void parse_name (char *, int, char **, int *, char **);
 
94
 
 
95
static char *next_tok (char *t) {
 
96
    while (*t++); /* That was easy */
 
97
    return t;
 
98
}
 
99
 
 
100
/* Check for possible file and target completions. Return non-zero if
 
101
 * the caller needs to re-output the command line.  */
 
102
static int tab_complete(void) {
 
103
    int image_len, defpart, part, ret = 0;
 
104
    char *device;
 
105
    char *p = cfg_get_strg (0, "partition");
 
106
    char *kname, *r;
 
107
 
 
108
    if ((r = strrchr(cbuff, ' ')) == NULL)
 
109
        r = strdup(cbuff);
 
110
    else
 
111
        r = strdup(r + 1);
 
112
 
 
113
    if (p && *p >= '1' && *p <= '8' && !p[1])
 
114
        defpart = *p - '0';
 
115
    else {
 
116
        silo_fatal("\nDefault partition could not be found");
 
117
        free(r);
 
118
        return 1;
 
119
    }
 
120
 
 
121
    parse_name (r, defpart, &device, &part, &kname);
 
122
    if (!kname) {
 
123
        /* Maybe this isn't a disk file. Maybe it's a silo.conf defined
 
124
         * alias/label.  */
 
125
        if (tab_ambiguous) {
 
126
            ret = cfg_print_images (NULL, r);
 
127
        } else {
 
128
            char *addr = (char *)0x4000;
 
129
            int count = cfg_print_images (addr, r);
 
130
            if (*addr) {
 
131
                int len = strlen(r);
 
132
                int len2 = strlen(cbuff);
 
133
                /* We have some completions... */
 
134
                if (count == 1) {
 
135
                    /* Just one, complete it... */
 
136
                    while (addr[len]) {
 
137
                        cbuff[len2] = addr[len];
 
138
                        cbuff[len2 + 1] = 0;
 
139
                        prom_puts(cbuff + len2, 1);
 
140
                        len++; len2++;
 
141
                    }
 
142
                    cbuff[len2] = ' ';
 
143
                    cbuff[len2 + 1] = 0;
 
144
                    prom_puts(cbuff + len2, 1);
 
145
                } else if (count > 1) { /* This should always be true, if we get here */
 
146
                    /* Complete the line as much as possible */
 
147
                    int common = 1, orig = len, i;
 
148
                    while (common && addr[len]) {
 
149
                        char *cur = next_tok(addr);
 
150
                        for (i = 1; i < count && common; i++, cur = next_tok(cur))
 
151
                            if (addr[len] != cur[len])
 
152
                                common = 0;
 
153
 
 
154
                        if (common) {
 
155
                            cbuff[len2] = addr[len];
 
156
                            cbuff[len2 + 1] = 0;
 
157
                            prom_puts(cbuff + len2, 1);
 
158
                            len++; len2++;
 
159
                        }
 
160
                    }
 
161
                    if (orig == len)
 
162
                        tab_ambiguous = 1;
 
163
                }
 
164
            } else
 
165
                tab_ambiguous = 1;
 
166
        }
 
167
    } else {
 
168
        if (!device) device = cfg_get_strg (0, "device");
 
169
 
 
170
        if (silo_load_file(device, part, kname, (unsigned char *) 0x4000,
 
171
                           (unsigned char *) &_start, &image_len,
 
172
                           LOADFILE_LS_MATCH|LOADFILE_QUIET, 0))
 
173
            if (do_ls((unsigned char *)0x4000, &tab_ambiguous))
 
174
                ret = 1;
 
175
    }
 
176
 
 
177
    free(r);
 
178
    return ret;
 
179
}
 
180
 
 
181
static void maintabfunc (void)
 
182
{
 
183
    if (cbuff[0] == 0) {
 
184
        /* Nothing on the command line, just list the possible images from
 
185
         * the config file.  */
 
186
        if (cfg_print_images (NULL, NULL))
 
187
            printf ("boot: %s", cbuff);
 
188
    } else {
 
189
        /* If tab_complete() returns non-zero, then it just listed
 
190
         * possible completions, and we need to redo our command line.  */
 
191
        if (tab_complete())
 
192
            printf ("boot: %s", cbuff);
 
193
    }
 
194
    return;
 
195
}
 
196
 
 
197
static void parse_name (char *imagename, int defpart, char **device,
 
198
                        int *part, char **kname)
 
199
{
 
200
    static char parsebuf[1024];
 
201
 
 
202
    strcpy (parsebuf, imagename);
 
203
    imagename = parsebuf;
 
204
    *device = 0;
 
205
    *kname = 0;
 
206
    if (prom_vers == PROM_V0) {
 
207
        static char v0_buffer[20];
 
208
        *kname = silo_v0_device(imagename);
 
209
        if (*kname) {
 
210
            memcpy (v0_buffer, imagename, *kname - imagename + 1);
 
211
            v0_buffer [*kname - imagename + 1] = 0;
 
212
            (*kname)++;
 
213
            *device = v0_buffer;
 
214
        }  else
 
215
            *kname = imagename;
 
216
    } else {
 
217
        *kname = strchr (imagename, ';');
 
218
        if (!*kname)
 
219
            *kname = imagename;
 
220
        else {
 
221
            **kname = 0;
 
222
            (*kname)++;
 
223
            *device = imagename;
 
224
        }
 
225
    }
 
226
    /* Range */
 
227
    if (**kname >= '0' && **kname <= '8' && (*kname)[1] == '[') {
 
228
        *part = **kname - '0';
 
229
        (*kname)++;
 
230
        return;
 
231
    }
 
232
    if (**kname == '[') {
 
233
        *part = 0;
 
234
        return;
 
235
    }
 
236
    /* Path */
 
237
    if (**kname >= '1' && **kname <= '8') {
 
238
        if ((*kname)[1] == '/' || !(*kname)[1]) {
 
239
            *part = **kname - '0';
 
240
            if (!(*kname)[1]) {
 
241
                *kname = 0;
 
242
            } else
 
243
                (*kname)++;
 
244
        }
 
245
    } else if (**kname == '/') {
 
246
        if (defpart != -2) {
 
247
            if (defpart != -1)
 
248
                *part = defpart;
 
249
            else
 
250
                *part = 1;
 
251
        }
 
252
    } else
 
253
        *kname = 0;
 
254
}
 
255
 
 
256
static void check_initrd (char *label, int defpart, char *defdevice)
 
257
{
 
258
    char *p;
 
259
    
 
260
    initrd_string = cfg_get_strg (label, "initrd");
 
261
    if (initrd_string) {
 
262
        initrd_defpart = defpart;
 
263
        initrd_defdevice = defdevice;
 
264
        initrd_size = 0;
 
265
        p = cfg_get_strg (label, "initrd-size");
 
266
        if (p) initrd_size = atoi (p);
 
267
        initrd_prompt = cfg_get_flag (label, "initrd-prompt");
 
268
    }
 
269
}
 
270
 
 
271
static int dig_into_params (char *params)
 
272
{
 
273
    char *p, *q;
 
274
    char *last_root = 0;
 
275
    int root_found = 0;
 
276
 
 
277
    p = params;    
 
278
    for (;;) {
 
279
        while (*p == ' ') p++;
 
280
        if (!*p) break;
 
281
        if (!strncmp (p, "initrd", 6)) {
 
282
            root_found = 1;
 
283
            p += 6;
 
284
            if (*p == '=') {
 
285
                for (q = p++; *q && *q != ' '; q++);
 
286
                if (p != q) {
 
287
                    initrd_string = malloc (q - p + 1);
 
288
                    memcpy (initrd_string, p, q - p);
 
289
                    initrd_string [q - p] = 0;
 
290
                    memset (p - 7, ' ', q - p + 7);
 
291
                }
 
292
            } else if (!strncmp (p, "-prompt", 7)) {
 
293
                initrd_prompt = 1;
 
294
                memset (p - 6, ' ', 7 + 6);
 
295
            } else if (!strncmp (p, "-size=", 6)) {
 
296
                int i;
 
297
                p += 6;
 
298
                i = atoi (p);
 
299
                if (i > 0) {
 
300
                    initrd_size = i;
 
301
                    for (q = p; *q >= '0' && *q <= '9'; q++);
 
302
                    memset (p - 12, ' ', q - p + 12);
 
303
                }
 
304
            }
 
305
        } else if (!strncmp (p, "pause-after", 11)) {
 
306
            pause_after = 1;
 
307
            memset (p, ' ', 11);
 
308
        } else if (!strncmp (p, "show-arguments", 14)) {
 
309
            show_arguments = 1;
 
310
            memset (p, ' ', 14);
 
311
        } else if (!strncmp (p, "root=", 5)) {
 
312
            root_found = 1;
 
313
            if (last_root) {
 
314
                while (*last_root != ' ') *last_root++ = ' ';
 
315
            }
 
316
            last_root = p;
 
317
        } else if (!strncmp (p, "nfsroot=", 8)) {
 
318
            root_found = 1;
 
319
        }
 
320
        while (*p && *p != ' ') p++;
 
321
    }
 
322
    return root_found;
 
323
}
 
324
 
 
325
static void check_password(char *str)
 
326
{
 
327
    int i;
 
328
    
 
329
    for (i = 0; i < 3; i++) {
 
330
        printf ("\n%sassword: ", str);
 
331
        passwdbuff[0] = 0;
 
332
        silo_cmdedit((void (*)(void)) 0, 1);
 
333
        printf ("\n");
 
334
        if (!strcmp (password, passwdbuff))
 
335
            return;
 
336
        if (i < 2)
 
337
            printf ("Wrong password. Please try again...");
 
338
    }
 
339
    printf ("Seems like you don't know the access password...\n");
 
340
    prom_halt();
 
341
}
 
342
 
 
343
static char *ls_options(char *parms)
 
344
{
 
345
    char *p = parms;
 
346
    ls_opt = 0;
 
347
    if (*parms == '-') {
 
348
        for (p = parms + 1;*p && *p != ' ';p++) {
 
349
            switch (*p) {
 
350
            case 'l': ls_opt |= LSOPT_L; break;
 
351
            case 't': ls_opt |= LSOPT_T; break;
 
352
            case 'r': ls_opt |= LSOPT_R; break;
 
353
            default:
 
354
                printf ("Unhandled options to ls: `%s' - only l, t and r supported\n", parms);
 
355
                break;
 
356
            }
 
357
        }
 
358
        while (*p == ' ') p++;
 
359
    }
 
360
    return p;
 
361
}
 
362
 
 
363
static int get_params (char **device, int *part, char **kname, char **proll,
 
364
                       char **params)
 
365
{
 
366
    int defpart = -1;
 
367
    char *defdevice = 0;
 
368
    char *p, *q;
 
369
    int c;
 
370
    char *imagename = 0, *label = 0;
 
371
    int timeout = -1, beg = 0, end;
 
372
    static char buffer[2048], buffer2[2048];
 
373
    static char prollb[256];    /* Hmm */
 
374
    static int first = 1;
 
375
    int from_prom = 0;
 
376
    int from_siloconf = 0;
 
377
    static int no_prom_args = 0;
 
378
    int tabbedout = 0;
 
379
 
 
380
#ifndef TFTP
 
381
    if (raid_dsk_number) {
 
382
        defpart = silo_conf_parts[raid_dsk_number - 1];
 
383
        if (defpart < 1 || defpart > 8)
 
384
            defpart = -1;
 
385
    }
 
386
#endif
 
387
    load_cmd = CMD_BOOT;    
 
388
    other = 0;
 
389
    fill_reboot_cmd = 0;
 
390
    solaris = 0;
 
391
    initrd_string = 0;
 
392
    pause_after = 0;
 
393
    reboot = 0;
 
394
    *proll = 0;
 
395
    silo_cmdinit();
 
396
    *params = "";
 
397
    if (useconf) {
 
398
        defdevice = cfg_get_strg (0, "device");
 
399
        if (defpart == -1) {
 
400
            /* For RAID1 avoid using this at all, it makes no sense
 
401
               anyway */
 
402
            p = cfg_get_strg (0, "partition");
 
403
            if (p && *p >= '1' && *p <= '8' && !p[1])
 
404
                defpart = *p - '0';
 
405
        }
 
406
        if (first) {
 
407
            first = 0;
 
408
            p = cfg_get_strg (0, "timeout");
 
409
            if (p && *p)
 
410
                timeout = atoi (p);
 
411
            if (no_prom_args) p = 0;
 
412
            else p = silo_get_bootargs(0);
 
413
            if (p) while (*p == ' ') p++;
 
414
            if (p && *p) {
 
415
                for (q = p; *q && *q != ' '; q++);
 
416
                if (*q == ' ') {
 
417
                    *q++ = 0;
 
418
                    while (*q == ' ') q++;
 
419
                    if (*q) *params = q;
 
420
                }
 
421
                imagename = p;
 
422
                from_prom = 1;
 
423
                printf ("\n");
 
424
            } else if (!timeout) {
 
425
                printf ("boot: ");
 
426
                c = prom_nbgetchar ();
 
427
                if (c != -1 && c != '\n' && c != '\r') {
 
428
                    if (c == '\t') {
 
429
                        maintabfunc ();
 
430
                        tabbedout = 1;
 
431
                    } else if (c >= ' ') {
 
432
                        tab_ambiguous = 0;
 
433
                        cbuff[0] = c;
 
434
                        cbuff[1] = 0;
 
435
                    }
 
436
                } else {
 
437
                    imagename = cfg_get_default ();
 
438
                    printf ("\n");
 
439
                }
 
440
            } else if (timeout != -1) {
 
441
                if (!timer_status) {
 
442
                    if (!init_timer ()) timer_status = 1;
 
443
                    else timer_status = -1;
 
444
                } else
 
445
                    timer_status++;
 
446
                if (timer_status <= 0) {
 
447
                    printf ("\nYour timeout %d.%ds will never expire, since counter couldn't"
 
448
                            "\nbe initialized\nboot: ", timeout/10, timeout % 10);
 
449
                } else {
 
450
                    printf ("boot: ");
 
451
                    reset_ticks ();
 
452
                    c = prom_nbgetchar ();
 
453
                    if (c == -1) {
 
454
                        beg = get_ticks ();
 
455
                        end = beg + 10 * timeout;
 
456
                        do {
 
457
                            c = prom_nbgetchar ();
 
458
                            if (c != -1)
 
459
                                break;
 
460
                        } while (get_ticks () <= end);
 
461
                    }
 
462
                    if (c != -1 && c != '\n' && c != '\r') {
 
463
                        if (c == '\t') {
 
464
                            maintabfunc ();
 
465
                            tabbedout = 1;
 
466
                        } else if (c >= ' ') {
 
467
                            tab_ambiguous = 0;
 
468
                            cbuff[0] = c;
 
469
                            cbuff[1] = 0;
 
470
                            if (cfg_get_flag (cbuff, "single-key"))
 
471
                                imagename = cbuff;
 
472
                        }
 
473
                    } else {
 
474
                        imagename = cfg_get_default ();
 
475
                        printf ("\n");
 
476
                    }
 
477
                    if (timer_status >= 1) {
 
478
                        timer_status--;
 
479
                        close_timer ();
 
480
                    }
 
481
                }
 
482
            }
 
483
        }
 
484
        if (!imagename) {
 
485
            if ((!*cbuff || (timeout > 0 && timer_status < 0)) && !tabbedout)
 
486
                printf ("boot: ");
 
487
            silo_cmdedit(maintabfunc, 0);
 
488
            if (*cbuff == ' ') {
 
489
                for (p = cbuff; *p == ' '; p++);
 
490
                q = cbuff;
 
491
                while ((*q++ = *p++) != 0);
 
492
            }
 
493
            strcpy (given_bootargs, cbuff);
 
494
            given_bootargs_by_user = 1;
 
495
            printf ("\n");
 
496
            if (!*cbuff)
 
497
                imagename = cfg_get_default ();
 
498
            else {
 
499
                p = strchr (cbuff, ' ');
 
500
                if (!p)
 
501
                    *params = "";
 
502
                else {
 
503
                    *p++ = 0;
 
504
                    while (*p && *p <= ' ')
 
505
                        p++;
 
506
                    *params = p;
 
507
                }
 
508
                imagename = cbuff;
 
509
            }
 
510
        }
 
511
        p = cfg_get_strg (imagename, "image");
 
512
        if (p && *p) {
 
513
            label = imagename;
 
514
            imagename = p;
 
515
        } else
 
516
            label = 0;
 
517
        p = cfg_get_strg (0, "pause-message");
 
518
        if (p) pause_message = p;
 
519
        if (label) {
 
520
            if (**params && password)
 
521
                check_password ("To specify image arguments you need to enter your p");
 
522
            from_siloconf = 1;
 
523
            defdevice = cfg_get_strg (label, "device");
 
524
#ifndef TFTP
 
525
            if (!raid_dsk_number)
 
526
#endif
 
527
            {
 
528
                p = cfg_get_strg (label, "partition");
 
529
                if (p && *p >= '1' && *p <= '8' && !p[1])
 
530
                    defpart = *p - '0';
 
531
            }
 
532
            *buffer = 0;
 
533
            q = buffer;
 
534
            if (cfg_get_flag (label, "fill-reboot-cmd"))
 
535
                fill_reboot_cmd = 1;
 
536
            if (cfg_get_strg (label, "other"))
 
537
                other = 1;
 
538
            else if (cfg_get_flag (label, "solaris"))
 
539
                solaris = 1;
 
540
            p = cfg_get_strg (label, "literal");
 
541
            if (!p && other)
 
542
                p = cfg_get_strg (label, "append");
 
543
            if (p) {
 
544
                strcpy (q, p);
 
545
                q = strchr (q, 0);
 
546
                if (**params) {
 
547
                    if (*p)
 
548
                        *q++ = ' ';
 
549
                    strcpy (q, *params);
 
550
                }
 
551
            } else if (!solaris && !other) {
 
552
                p = cfg_get_strg (label, "root");
 
553
                if (p) {
 
554
                    strcpy (q, "root=");
 
555
                    strcpy (q + 5, p);
 
556
                    q = strchr (q, 0);
 
557
                    *q++ = ' ';
 
558
                }
 
559
                if (cfg_get_flag (label, "read-only")) {
 
560
                    strcpy (q, "ro ");
 
561
                    q += 3;
 
562
                }
 
563
                if (cfg_get_flag (label, "read-write")) {
 
564
                    strcpy (q, "rw ");
 
565
                    q += 3;
 
566
                }
 
567
                p = cfg_get_strg (label, "ramdisk");
 
568
                if (p) {
 
569
                    strcpy (q, "ramdisk=");
 
570
                    strcpy (q + 8, p);
 
571
                    q = strchr (q, 0);
 
572
                    *q++ = ' ';
 
573
                }
 
574
                p = cfg_get_strg (label, "append");
 
575
                if (p) {
 
576
                    strcpy (q, p);
 
577
                    q = strchr (q, 0);
 
578
                    *q++ = ' ';
 
579
                }
 
580
                check_initrd (label, defpart, defdevice);
 
581
                if (**params)
 
582
                        strcpy (q, *params);
 
583
                p = cfg_get_strg (label, "proll");
 
584
                if (p && strlen (p) < sizeof(prollb)-1) {
 
585
                    strcpy (prollb, p);
 
586
                    *proll = prollb;
 
587
                }
 
588
            }
 
589
            if (other) {
 
590
                char *oth_device = 0;
 
591
                char *oth_kname = 0;
 
592
                
 
593
                other_part = -1;
 
594
                parse_name (imagename, -1, &oth_device, &other_part, &oth_kname);
 
595
                if (other_part == -1 || oth_kname) {
 
596
                    printf ("Wrong syntax for other= parameter. The parameter should be\n");
 
597
                    if (prom_vers == PROM_V0)
 
598
                        printf ("either a single number 1-8 (ie. partition of the current disk)\n"
 
599
                                "or sd(X,Y,Z)N (ie. some other disk plus partition number)\n"
 
600
                                "e.g. sd(0,3,2)4\n");
 
601
                    else
 
602
                        printf ("either a single number 1-8 (ie. partition of the current disk)\n"
 
603
                                "or /prom/path/name;N (ie. some other disk plus partition number)\n"
 
604
                                "e.g. /iommu/sbus/espdma/esp/sd@3,0;3 \n");
 
605
                    *kname = 0;
 
606
                    return 0;
 
607
                }
 
608
                if (!oth_device) {
 
609
                    if (defdevice)
 
610
                        oth_device = defdevice;
 
611
                    else
 
612
                        oth_device = silo_disk_get_bootdevice();
 
613
                }
 
614
                strcpy (other_device, oth_device);
 
615
                p = cfg_get_strg (label, "bootblock");
 
616
                if (p)
 
617
                    imagename = p;
 
618
                else {
 
619
                    static char bufx[8];
 
620
                    
 
621
                    if (architecture == sun4u)
 
622
                        reboot = 1;
 
623
                    strcpy (bufx, "x[1-16]");
 
624
                    *bufx = other_part + '0';
 
625
                    defdevice = other_device;
 
626
                    defpart = other_part;
 
627
                }
 
628
            }
 
629
            pause_after = cfg_get_flag (label, "pause-after");
 
630
            p = cfg_get_strg (label, "pause-message");
 
631
            if (p) pause_message = p;
 
632
            *params = buffer;
 
633
        }
 
634
    } else {
 
635
        if (first) {
 
636
            first = 0;
 
637
            if (no_prom_args) p = 0;
 
638
            else p = silo_get_bootargs(0);
 
639
            if (p) while (*p == ' ') p++;
 
640
            if (p && *p) {
 
641
                for (q = p; *q && *q != ' '; q++);
 
642
                if (*q == ' ') {
 
643
                    *q++ = 0;
 
644
                    while (*q == ' ') q++;
 
645
                    if (*q) *params = q;
 
646
                }
 
647
                imagename = p;
 
648
                from_prom = 1;
 
649
                printf ("\n");
 
650
            }
 
651
        }
 
652
        if (!imagename) {
 
653
            printf ("boot: ");
 
654
            silo_cmdedit((void (*)(void)) 0, 0);
 
655
            if (*cbuff == ' ') {
 
656
                for (p = cbuff; *p == ' '; p++);
 
657
                q = cbuff;
 
658
                while ((*q++ = *p++) != 0);
 
659
            }
 
660
            strcpy (given_bootargs, cbuff);
 
661
            given_bootargs_by_user = 1;
 
662
            printf ("\n");
 
663
            p = strchr (cbuff, ' ');
 
664
            if (!p)
 
665
                *params = "";
 
666
            else {
 
667
                *p = 0;
 
668
                p++;
 
669
                while (*p && *p <= ' ')
 
670
                    p++;
 
671
                *params = p;
 
672
            }
 
673
            imagename = cbuff;
 
674
        }
 
675
    }
 
676
    if (!strcmp (imagename, "halt"))
 
677
        return 1;
 
678
    if (!label && password)
 
679
        check_password ("To boot a custom image you need to enter your p");
 
680
    if (!strcmp (imagename, "xxdebug"))
 
681
        return 2;
 
682
    if (!strcmp (imagename, "help")) {
 
683
        if (prom_vers == PROM_V0)
 
684
            printf ("You have to type image name as {XY(...)}partno/path or {XY(...)}partno[mm-nn],\n"
 
685
                    "where XY(...) is the optional v0 prom device name (if partition number is specified,\n"
 
686
                    "it should be Sun partition number (zero based) of any partition starting at cyl. 0)\n"
 
687
                    "({} means that it is optional) and partno is a Linux partition number from 1 to 8.\n"
 
688
                    "You can specify a path into filesystem (ext2fs, ufs) - has to start with / - or\n"
 
689
                    "[mm-nn] as range of phys. blocks (512B).\n");
 
690
        else
 
691
            printf ("You have to type image name as [prom_path;]partno/path, where partno is a\n"
 
692
                    "number from 1 to 8. If partno is not specified, either default from silo.conf\n"
 
693
                    "(partition=X) or 1 will be used. Instead of /path you can type [mm-nn] to\n"
 
694
                    "specify a range of phys. blocks (512B)\n");
 
695
        printf ("If you use silo.conf and have some image= sections there, you can type\n"
 
696
                "its label or alias name instead of the above described image names.\n"
 
697
                "Pressing just enter will load default image with default arguments. Special\n"
 
698
                "image names `halt' and `help' can be used to fall back to PROM or display\n"
 
699
                "help. All three types of image names can be followed by additional arguments.\n"
 
700
                "Examples:\n");
 
701
        if (prom_vers == PROM_V0)
 
702
            printf ("  /boot/vmlinux.gz root=/dev/sda4\n"
 
703
                    "  2/boot/mykernel.gz root=/dev/sda2\n"
 
704
                    "  sd(0,6,2)5/boot/old.b\n"
 
705
                    "  sd(1,2,0)[1-16] root=/dev/sda4\n");
 
706
        else
 
707
            printf ("  /iommu/sbus/espdma/esp/sd@3,0;4/boot/vmlinux.gz root=/dev/sda4\n"
 
708
                    "  1/boot/old.b\n"
 
709
                    "  /sbus/espdma/esp/sd@0,0;3[1-16] root=/dev/sda4\n");
 
710
        printf ("  linux root=/dev/sda4\n"
 
711
                "  live\n");
 
712
        *kname = 0;
 
713
        return 0;
 
714
    }
 
715
    strcpy (buffer2, imagename);
 
716
    *part = -2;
 
717
    if (!label && (!strcmp (imagename, "cat") || !strcmp (imagename, "ls"))) {
 
718
        if (*imagename == 'c')
 
719
            load_cmd = CMD_CAT;
 
720
        else {
 
721
            load_cmd = CMD_LS;
 
722
            *params = ls_options (*params);
 
723
        }
 
724
        imagename = *params;
 
725
        p = strchr (imagename, ' ');
 
726
        if (!p)
 
727
            *params = "";
 
728
        else {
 
729
            *p++ = 0;
 
730
            while (*p && *p <= ' ')
 
731
                p++;
 
732
            *params = p;
 
733
        }
 
734
    } else if (label && (!strncmp (imagename, "cat ", 4) || !strncmp (imagename, "ls ", 3))) {
 
735
        if (*imagename == 'c') {
 
736
            load_cmd = CMD_CAT;
 
737
            imagename += 4;
 
738
            while (*imagename == ' ') imagename++;
 
739
        } else {
 
740
            load_cmd = CMD_LS;
 
741
            imagename += 3;
 
742
            while (*imagename == ' ') imagename++;
 
743
            imagename = ls_options (imagename);
 
744
        }
 
745
    }
 
746
    parse_name (imagename, -2, device, part, kname);
 
747
    if (!*device)
 
748
        *device = defdevice;
 
749
    if (*kname && *part == -2) {
 
750
        if (defpart != -1)
 
751
            *part = defpart;
 
752
        else
 
753
            *part = 1;
 
754
    }
 
755
    if (!*kname) {
 
756
        if (*part != -2) {
 
757
            other_part = *part;
 
758
            if (!*device)
 
759
                strcpy (other_device, silo_disk_get_bootdevice());
 
760
            else
 
761
                strcpy (other_device, *device);
 
762
            p = strstr (*params, "bootblock=");
 
763
            if (p && (p == *params || p[-1] == ' ') && p[10] && p[10] != ' ') {
 
764
                char tmp[512], *q;
 
765
                
 
766
                q = tmp; 
 
767
                p += 10;
 
768
                while (*p && *p != ' ')
 
769
                    *q++ = *p++;
 
770
                *q = 0;
 
771
                parse_name (tmp, defpart, device, part, kname);
 
772
                if (*kname) {
 
773
                    p = strstr (*params, "bootblock=");
 
774
                    memset (p, ' ', q - tmp + 10);
 
775
                    other = 1;
 
776
                    return 0;
 
777
                } else {
 
778
                    printf ("Syntax of your bootblock= parameter is wrong. Please see help\n");
 
779
                }
 
780
            } else {
 
781
                other = 1;
 
782
                *kname = strdup ("[1-16]");
 
783
                if (architecture == sun4u)
 
784
                    reboot = 1;
 
785
                return 0;
 
786
            }
 
787
        } else {
 
788
            if (defpart != -1)
 
789
                *part = defpart;
 
790
            else
 
791
                *part = 1;
 
792
        }
 
793
        if (from_prom) {
 
794
            int options_node, len;
 
795
            int is_from_prom = 0;
 
796
            char *v = "";
 
797
            char buffer3[2048];
 
798
            
 
799
            if ((options_node = prom_searchsiblings (prom_getchild (prom_root_node), "options")) != 0) {
 
800
                if (prom_vers != PROM_V0) {
 
801
                    prom_getstring (options_node, v = "boot-file", buffer3, 2048);
 
802
                    len = prom_getproplen (options_node, v);
 
803
                    if (len < 0) len = 0;
 
804
                    buffer3[len] = 0;
 
805
                    if (!strcmp (buffer3, my_bootargs))
 
806
                        is_from_prom = 1;
 
807
                    else {
 
808
                        prom_getstring (options_node, v = "diag-file", buffer3, 2048);
 
809
                        len = prom_getproplen (options_node, v);
 
810
                        if (len < 0) len = 0;
 
811
                        buffer3[len] = 0;
 
812
                        if (!strcmp (buffer3, my_bootargs))
 
813
                            is_from_prom = 1;
 
814
                    }
 
815
                } else {
 
816
                    prom_getstring (options_node, v = "boot-from", buffer3, 2048);
 
817
                    len = prom_getproplen (options_node, v);
 
818
                    if (len < 0) len = 0;
 
819
                    buffer3[len] = 0;
 
820
                    if (!strcmp (buffer3, my_bootargs))
 
821
                        is_from_prom = 1;
 
822
                }
 
823
            }
 
824
            if (is_from_prom) {
 
825
                first = 1;
 
826
                no_prom_args = 1;
 
827
                *given_bootargs = 0;
 
828
                given_bootargs_by_user = 1;
 
829
                printf ("You have `%s' string in your %s variable.\n"
 
830
                        "This string doesn't contain valid arguments to SILO.\n"
 
831
                        "Consider doing setenv %s. Anyway, SILO will continue as\n"
 
832
                        "if there were no arguments in %s.\n", buffer3, v, v, v);
 
833
                return 0;
 
834
            }
 
835
        }
 
836
        printf ("Your imagename `%s' and arguments `%s' have either wrong syntax,\n"
 
837
                "or describe a label which is not present in silo.conf\n"
 
838
                "Type `help' at the boot: prompt if you need it and then try again.\n", buffer2, *params ? *params : "");
 
839
    } else if (!solaris) {
 
840
        p = strstr (*params, "solaris");
 
841
        if (p && (p == *params || p[-1] == ' ') && (!p[7] || p[7] == ' ')) {
 
842
            memset (p, ' ', 7);
 
843
            solaris = 1;
 
844
        } else if (!strcmp (*kname, "/kernel/unix"))
 
845
            solaris = 1;
 
846
        if (!fill_reboot_cmd) {
 
847
            p = strstr (*params, "fill-reboot-cmd");
 
848
            if (p && (p == *params || p[-1] == ' ') && (!p[15] || p[15] == ' ')) {
 
849
                memset (p, ' ', 15);
 
850
                fill_reboot_cmd = 1;
 
851
            }
 
852
        }
 
853
    }
 
854
    return 0;
 
855
}
 
856
 
 
857
static void initrd_lenfunc (int len, char **filebuffer, char **filelimit)
 
858
{
 
859
    extern unsigned long long initrd_phys;
 
860
 
 
861
    initrd_start = memory_find ((len + 16383) & ~16383);
 
862
    if (!initrd_start) {
 
863
        silo_fatal("You do not have enough continuous available memory "
 
864
                   "for such initial ramdisk.");
 
865
        prom_halt ();
 
866
    }
 
867
    initrd_size = len;
 
868
    *filebuffer = initrd_start;
 
869
    *filelimit = initrd_start + ((len + 16383) & ~16383);
 
870
    printf("Loading initial ramdisk (%d bytes at 0x%Lx phys, 0x%x virt)...\n", len,
 
871
           initrd_phys, initrd_start);
 
872
}
 
873
 
 
874
static int parse_executable (unsigned char *base, int image_len, unsigned int *poff,
 
875
                             int *plen, unsigned *pstart, char *image_name)
 
876
{
 
877
    int isfile = 0;
 
878
    union {
 
879
        char *b;
 
880
        struct aout_hdr *a;
 
881
        Elf32_Ehdr *e;
 
882
        Elf64_Ehdr *f;
 
883
    } hp;
 
884
    unsigned off = 0;
 
885
    int len = 0;
 
886
    unsigned st = (unsigned int) base;
 
887
 
 
888
    /* By this point the first sector is loaded (and the rest of */
 
889
    /* the kernel) so we check if it is an executable file, either */
 
890
    /* an a.out or an elf binary */
 
891
 
 
892
    hp.b = (char *)base;
 
893
    if (hp.a->magic == 0x01030107) {
 
894
        if (solaris) {
 
895
            printf ("\nYour Solaris `ufsboot' is not an ELF image. Try again.\n");
 
896
            return -1;
 
897
        }
 
898
        off = sizeof (struct aout_hdr);
 
899
        if (image_len > hp.a->ltext + hp.a->ldata)
 
900
            len = hp.a->ltext + hp.a->ldata;
 
901
        else
 
902
            len = image_len;
 
903
        isfile = 1;
 
904
    } else if (hp.e->e_ident[EI_MAG0] == ELFMAG0 &&
 
905
                hp.e->e_ident[EI_MAG1] == ELFMAG1 &&
 
906
                hp.e->e_ident[EI_MAG2] == ELFMAG2 &&
 
907
                hp.e->e_ident[EI_MAG3] == ELFMAG3) {
 
908
 
 
909
        if (hp.e->e_ident[EI_DATA] != ELFDATA2MSB) {
 
910
            silo_fatal("Image is not a MSB ELF");
 
911
            prom_halt ();
 
912
        }
 
913
        if (hp.e->e_ident[EI_CLASS] == ELFCLASS32) {
 
914
            Elf32_Phdr *p;
 
915
 
 
916
            p = (Elf32_Phdr *) (hp.b + hp.e->e_phoff);
 
917
            if (p->p_type != PT_LOAD) {
 
918
                silo_fatal("Cannot find a loadable segment in your "
 
919
                           "ELF image");
 
920
                prom_halt ();
 
921
            }
 
922
            if (solaris) {
 
923
                int i;
 
924
                unsigned long sa = (unsigned long)&_start;
 
925
 
 
926
                for (i = 0; i < hp.e->e_phnum; i++, p++) {
 
927
                    if (p->p_vaddr < 0x4000 + image_len ||
 
928
                                p->p_vaddr + p->p_memsz >= sa) {
 
929
                        silo_fatal("Unable to handle your "
 
930
                                   "Solaris `ufsboot' bootloader.");
 
931
                        prom_halt ();
 
932
                    }
 
933
                    memcpy ((char *)p->p_vaddr,
 
934
                                (char *)(0x4000 + p->p_offset), p->p_filesz);
 
935
                    if (p->p_filesz < p->p_memsz)
 
936
                        memset ((char *)(p->p_vaddr + p->p_filesz), 0,
 
937
                                p->p_memsz - p->p_filesz);
 
938
                }
 
939
                isfile = 1;
 
940
                st = hp.e->e_entry;
 
941
            } else {
 
942
                    int i;
 
943
                    unsigned long n;
 
944
 
 
945
                    Elf32_Phdr *q = p + 1;
 
946
                            
 
947
                    for (i = 1; i < hp.e->e_phnum; i++, q++) {
 
948
                        if (q->p_type != PT_LOAD)
 
949
                            break;
 
950
                        n = q->p_offset - p->p_offset;
 
951
                        if (q->p_vaddr - p->p_vaddr == n &&
 
952
                            q->p_paddr - p->p_paddr == n &&
 
953
                            p->p_memsz == p->p_filesz &&
 
954
                            p->p_memsz <= n) {
 
955
                                p->p_filesz = n + q->p_filesz;
 
956
                                p->p_memsz = n + q->p_memsz;
 
957
                        } else {
 
958
                            silo_fatal("Multiple loadable segments in "
 
959
                                       "your ELF image");
 
960
                            prom_halt();
 
961
                        }
 
962
                    }
 
963
                    off = p->p_offset + hp.e->e_entry - p->p_vaddr;
 
964
                    len = p->p_filesz;
 
965
                    if (len > image_len) len = image_len;
 
966
                    isfile = 1;
 
967
            }
 
968
        } else if (hp.e->e_ident[EI_CLASS] == ELFCLASS64) {
 
969
            Elf64_Phdr *p;
 
970
            unsigned long long n;
 
971
            int i;
 
972
            Elf64_Phdr *q;
 
973
 
 
974
            p = (Elf64_Phdr *) (hp.b + hp.f->e_phoff);
 
975
            if (p->p_type != PT_LOAD) {
 
976
                silo_fatal("Cannot find a loadable segment in your "
 
977
                           "ELF image");
 
978
                prom_halt ();
 
979
            }
 
980
            if (solaris) {
 
981
                int i;
 
982
                unsigned long sa = (unsigned long)&_start;
 
983
 
 
984
                for (i = 0; i < hp.f->e_phnum; i++, p++) {
 
985
                    if (p->p_vaddr < 0x4000 + image_len ||
 
986
                         p->p_vaddr + p->p_memsz >= sa) {
 
987
 
 
988
                         silo_fatal("Unable to handle your "
 
989
                                    "Solaris `ufsboot' bootloader.");
 
990
                         prom_halt ();
 
991
                    }
 
992
                    memcpy ((Elf64_Addr *)(long)(p->p_vaddr),
 
993
                                (Elf64_Addr *)(long)(0x4000 + p->p_offset),
 
994
                                p->p_filesz);
 
995
                    if (p->p_filesz < p->p_memsz)
 
996
                        memset ((Elf64_Addr *)(long)(p->p_vaddr + p->p_filesz),
 
997
                                0, p->p_memsz - p->p_filesz);
 
998
                }
 
999
                isfile = 1;
 
1000
                st = hp.f->e_entry;
 
1001
            } else {
 
1002
                    q = p + 1;
 
1003
                    for (i = 1; i < hp.f->e_phnum; i++, q++) {
 
1004
                        if (q->p_type != PT_LOAD)
 
1005
                            break;
 
1006
                        n = q->p_offset - p->p_offset;
 
1007
                        if (q->p_vaddr - p->p_vaddr == n &&
 
1008
                            q->p_paddr - p->p_paddr == n &&
 
1009
                            p->p_memsz == p->p_filesz &&
 
1010
                            p->p_memsz <= n) {
 
1011
 
 
1012
                            p->p_filesz = n + q->p_filesz;
 
1013
                            p->p_memsz = n + q->p_memsz;
 
1014
                        } else {
 
1015
                            silo_fatal("Multiple loadable segments "
 
1016
                                       "in your ELF image");
 
1017
                            prom_halt();
 
1018
                        }
 
1019
                    }
 
1020
            }
 
1021
            off = p->p_offset + hp.f->e_entry - p->p_vaddr;
 
1022
            len = p->p_filesz;
 
1023
            if (len > image_len) len = image_len;
 
1024
            isfile = 1;
 
1025
        }
 
1026
    }
 
1027
 
 
1028
    if (isfile) {
 
1029
        if (pstart != NULL)
 
1030
            *pstart = st;
 
1031
        *poff = off;
 
1032
        *plen = len;
 
1033
    } else {
 
1034
        printf ("\nUnknown image %s format\n", image_name);
 
1035
    }
 
1036
    return isfile;
 
1037
}
 
1038
 
 
1039
/* Here we are launched */
 
1040
int bootmain (void)
 
1041
{
 
1042
    unsigned off = 0;
 
1043
    int len = 0, image_len;
 
1044
    char *kname, *params, *device;
 
1045
    char *proll = 0;
 
1046
    unsigned char *image_base = (unsigned char *) 0x4000;
 
1047
    char *kernel_params;
 
1048
    int part;
 
1049
    int isfile, fileok = 0;
 
1050
    unsigned int ret_offset = 0;
 
1051
    char *params_device = 0;
 
1052
    int silo_conf_partition;
 
1053
 
 
1054
    prom_ranges_init ();
 
1055
    get_idprom();
 
1056
    architecture = silo_get_architecture();
 
1057
    strcpy (given_bootargs, silo_get_bootargs(1));
 
1058
    strcpy (my_bootargs, silo_get_bootargs(0));
 
1059
 
 
1060
#ifndef TFTP
 
1061
    if (silo_diskinit() == -1)
 
1062
        prom_halt ();
 
1063
#endif
 
1064
        
 
1065
    if (architecture == sun4u) {
 
1066
        char buffer[512], *p;
 
1067
        int node = prom_finddevice("/chosen");
 
1068
        if (node) {
 
1069
                prom_getstring(node, "bootpath", buffer, 512);
 
1070
                if (strstr(buffer, "fdthree")) {
 
1071
                        p = strchr (buffer, ':');
 
1072
                        if (p) *p = 0;
 
1073
                        node = prom_finddevice(buffer);
 
1074
                        if (node) {
 
1075
                                if (prom_getintdefault (node, "unit", 0) == 1)
 
1076
                                        floppyswap = 1;
 
1077
                        }
 
1078
                }
 
1079
        }
 
1080
    }
 
1081
 
 
1082
/* Here should be code #ifdef TFTP, that will handle loading of silo.conf via tftp and this code should be on the other side #ifndef TFTP */
 
1083
    silo_conf_partition = silo_conf_part;
 
1084
#ifndef TFTP
 
1085
    if (raid_dsk_number)
 
1086
        silo_conf_partition = silo_conf_parts[raid_dsk_number - 1];
 
1087
#endif
 
1088
    if (*silo_conf && silo_conf_partition >= 1 && silo_conf_partition <= 8) {
 
1089
        int len;
 
1090
        solaris = 0;
 
1091
        fileok = silo_load_file(0, silo_conf_partition, silo_conf,
 
1092
                                (unsigned char *) 0x4000,
 
1093
                                (unsigned char *) &_start,
 
1094
                                &len, LOADFILE_GZIP | LOADFILE_NO_ROTATE, 0);
 
1095
        if (!fileok || (unsigned) len >= 65535)
 
1096
            printf ("\nCouldn't load %s\n", silo_conf);
 
1097
        else {
 
1098
            if (!cfg_parse (silo_conf, (char *) 0x4000, len)) {
 
1099
                char *p, *q;
 
1100
                int len = 0;
 
1101
                int defpart = -1;
 
1102
#ifndef TFTP
 
1103
                if (raid_dsk_number)
 
1104
                    defpart = silo_conf_partition;
 
1105
#endif          
 
1106
                p = cfg_get_strg (0, "message");
 
1107
                if (p) {
 
1108
                    q = cfg_get_strg (0, "partition");
 
1109
                    if (q && *q >= '1' && *q <= '8' && !q[1])
 
1110
                        defpart = *q - '0';
 
1111
                    parse_name (p, defpart, &device, &part, &kname);
 
1112
                    if (kname) {
 
1113
                        if (!device)
 
1114
                            device = cfg_get_strg (0, "device");
 
1115
                        solaris = 0;
 
1116
                        if (silo_load_file(device, part, kname,
 
1117
                                           (unsigned char *) 0x4000,
 
1118
                                           (unsigned char *) &_start, &len,
 
1119
                                           LOADFILE_GZIP, 0)) {
 
1120
                            *(unsigned char *) (0x4000 + len) = 0;
 
1121
                            printf ("\n");
 
1122
                            print_message ((char *) 0x4000);
 
1123
                        }
 
1124
                    }
 
1125
                }
 
1126
                useconf = 1;
 
1127
                password = cfg_get_strg (0, "password");
 
1128
                if (password && !cfg_get_flag (0, "restricted")) {
 
1129
                    check_password ("P");
 
1130
                    password = 0;
 
1131
                }
 
1132
            } else {
 
1133
                printf ("Syntax error in %s\n"
 
1134
                        "Please check the file for obvious bugs, and if you think it is correct, get\n"
 
1135
                        "latest version of SILO. If problems still survive, contact the author\n", silo_conf);
 
1136
            }
 
1137
        }
 
1138
    } else
 
1139
        printf ("\n");
 
1140
    if (!useconf)
 
1141
        printf ("No config file loaded, you can boot just from this command line\n"
 
1142
        "Type [prompath;]part/path_to_image [parameters] on the prompt\n"
 
1143
          "E.g. /iommu/sbus/espdma/esp/sd@3,0;4/vmlinux root=/dev/sda4\n"
 
1144
                "or 2/vmlinux.live (to load vmlinux.live from 2nd partition of boot disk)\n");
 
1145
try_again:
 
1146
    isfile = 0;                 /* RC = 0 invalid file or not an executable */
 
1147
    while (!isfile) {
 
1148
        switch (get_params (&device, &part, &kname, &proll, &params)) {
 
1149
        case 1:
 
1150
            prom_halt ();
 
1151
        case 2:
 
1152
            prom_cmdline ();
 
1153
            continue;
 
1154
        }
 
1155
        if (!kname)
 
1156
            continue;
 
1157
            
 
1158
        if (other && reboot)
 
1159
            break;
 
1160
 
 
1161
        if (solaris) {
 
1162
            char *p = seed_part_into_device ((!device || !*device) ? silo_disk_get_bootdevice() : device, part);
 
1163
            strcpy (sol_params, p);
 
1164
            params_device = strchr (sol_params, 0) + 1;
 
1165
            strcpy (params_device, kname);
 
1166
            if (params && *params) {
 
1167
                strcat (params_device, " ");
 
1168
                strcat (params_device, params);
 
1169
            }
 
1170
        }
 
1171
 
 
1172
        if (load_cmd == CMD_BOOT && proll != 0) {
 
1173
            if (other || solaris) {
 
1174
                printf ("\nNeither \"other\" nor \"solaris\" are compatible with proll\n");
 
1175
                continue;
 
1176
            }
 
1177
            if (!silo_load_file(device, part, proll, (unsigned char *) 0x4000,
 
1178
                                (unsigned char *) 0x40000, &image_len,
 
1179
                                LOADFILE_GZIP, 0)) {
 
1180
                printf ("\nProll not found.... try again\n");
 
1181
                continue;
 
1182
            }
 
1183
            if (!parse_executable ((unsigned char *)0x4000, image_len, &off,
 
1184
                                    &len, NULL, proll))
 
1185
                continue;
 
1186
            memcpy ((char *) 0x4000, ((char *) 0x4000) + off, len);
 
1187
 
 
1188
            image_base = (unsigned char *) 0x40000;
 
1189
            if (!silo_load_file(device, part, kname, image_base,
 
1190
                                (unsigned char *) &_start, &image_len,
 
1191
                                LOADFILE_GZIP, 0)) {
 
1192
                printf ("\nImage not found.... try again\n");
 
1193
                continue;
 
1194
            }
 
1195
            if (!(isfile = parse_executable (image_base, image_len,
 
1196
                        &off, &len, NULL, kname)))
 
1197
                continue;
 
1198
            ret_offset = 0x4000;
 
1199
 
 
1200
        } else {
 
1201
            unsigned char *image_end = (unsigned char *)&_start;
 
1202
 
 
1203
            /* See if we can use some extra memory for the kernel */
 
1204
            if (!load_cmd) {
 
1205
                unsigned int size;
 
1206
                unsigned char *mem;
 
1207
 
 
1208
                size = 0x800000;
 
1209
                mem = (unsigned char *)image_memory_find(size);
 
1210
 
 
1211
                if (!mem) {
 
1212
                    size = 0x400000;
 
1213
                    mem = (unsigned char *)image_memory_find(size);
 
1214
                }
 
1215
 
 
1216
                if (mem) {
 
1217
                    image_base = mem;
 
1218
                    image_end = image_base + size - 0x4000;
 
1219
                    printf("Allocated %d Megs of memory at 0x%x for kernel\n",
 
1220
                           size >> 20, image_base - 0x4000);
 
1221
                }
 
1222
            }
 
1223
 
 
1224
            if (!silo_load_file(device, part, kname, image_base, image_end,
 
1225
                                &image_len, ((load_cmd == CMD_LS) ?
 
1226
                                             LOADFILE_LS :
 
1227
                                             LOADFILE_GZIP), 0)) {
 
1228
                printf ("\nImage not found.... try again\n");
 
1229
 
 
1230
                if (!load_cmd)
 
1231
                    image_memory_release();
 
1232
 
 
1233
                continue;
 
1234
            }
 
1235
 
 
1236
            if (load_cmd == CMD_CAT) {
 
1237
                *(image_base + image_len) = 0;
 
1238
                printf ("%s", image_base);
 
1239
                continue;
 
1240
            }
 
1241
 
 
1242
            if (load_cmd == CMD_LS) {
 
1243
                do_ls (image_base, NULL);
 
1244
                continue;
 
1245
            }
 
1246
 
 
1247
            isfile = parse_executable (image_base, image_len, &off, &len,
 
1248
                                       &ret_offset, kname);
 
1249
        }
 
1250
    }
 
1251
 
 
1252
    kernel_params = 0;
 
1253
    if (solaris) {
 
1254
        params = params_device;
 
1255
        params_device = sol_params;
 
1256
    } else if (!other) {
 
1257
        struct HdrS_struct *hdrs;
 
1258
 
 
1259
        params_device = 0;
 
1260
 
 
1261
        memcpy (image_base, image_base + off, len);
 
1262
 
 
1263
        hdrs = (struct HdrS_struct *)
 
1264
                silo_find_linux_HdrS((char *)image_base, image_len);
 
1265
 
 
1266
        if (hdrs && hdrs->ver < 0x300 && image_base != (unsigned char *)0x4000) {
 
1267
            /* Kernel doesn't support being loaded to other than
 
1268
             * phys_base, so let's try to copy it down there. */
 
1269
            if ((unsigned int)&_start - 0x4000 < len) {
 
1270
                /* Fuck, can't do that */
 
1271
                printf("Your kernel cannot fit into the memory destination. This\n"
 
1272
                       "can be resolved by recompiling the kernel with more devices\n"
 
1273
                       "built as modules, or upgrading your kernel to one that\n"
 
1274
                       "supports being loaded to higher memory areas (currently\n"
 
1275
                       "2.6.3+ or 2.4.26+).\n");
 
1276
                goto try_again;
 
1277
            }
 
1278
 
 
1279
            printf("Kernel doesn't support loading to high memory, relocating...");
 
1280
 
 
1281
            /* Ok, it fits, so copy it down there */
 
1282
            memcpy ((char *)0x4000, image_base, len);
 
1283
            image_base = (unsigned char *)0x4000;
 
1284
 
 
1285
            /* Readjust some things */
 
1286
            ret_offset = 0x4000;
 
1287
            hdrs = (struct HdrS_struct *)
 
1288
                silo_find_linux_HdrS((char *)image_base, image_len);
 
1289
 
 
1290
            printf("done.\n");
 
1291
        }
 
1292
 
 
1293
        if (hdrs) {
 
1294
            unsigned int linux_ver = hdrs->linux_ver;
 
1295
 
 
1296
            printf("Loaded kernel version %d.%d.%d\n", (linux_ver >> 16) & 0xff,
 
1297
                   (linux_ver >> 8) & 0xff, linux_ver & 0xff);
 
1298
 
 
1299
            if (fill_reboot_cmd && hdrs->ver >= 0x201) { /* ie. uses reboot_command */
 
1300
                char *q = (char *)hdrs->reboot_cmd_ptr_high;
 
1301
                char *r;
 
1302
 
 
1303
                /* On Ultra there is xword there, this hack makes
 
1304
                 * it work...
 
1305
                 */
 
1306
                if (q == (char *)0xfffff800 || !q)
 
1307
                       q = (char *)hdrs->reboot_cmd_ptr_low;
 
1308
                q = (char *)(((unsigned long)q)& 0x003fffff);
 
1309
                if (q >= (char *)0x4000 && q <= (char *)0x300000) {
 
1310
                    if (given_bootargs_by_user) {
 
1311
                        if (strlen (silo_disk_get_bootdevice()) <= 254) {
 
1312
                            strcpy (q, silo_disk_get_bootdevice());
 
1313
                            r = strchr (q, 0);
 
1314
                            if (strlen (given_bootargs) < 255 - (r - q)) {
 
1315
                                *r++ = ' ';
 
1316
                                strcpy (r, given_bootargs);
 
1317
                            }
 
1318
                        }
 
1319
                    } else if (strlen (given_bootargs) <= 255)
 
1320
                        strcpy (q, given_bootargs);
 
1321
                }
 
1322
            }
 
1323
            if (!dig_into_params (params) && !hdrs->root_dev) {
 
1324
                char *s1, *s2;
 
1325
 
 
1326
                s1 = cfg_get_strg(0, "root");
 
1327
                if (s1) {
 
1328
                    s2 = malloc(strlen(params) + 8 + strlen(s1));
 
1329
                    strcpy(s2, params);
 
1330
                    strcat(s2, " root=");
 
1331
                    strcat(s2, s1);
 
1332
                    params = s2;
 
1333
                }
 
1334
            }
 
1335
 
 
1336
            if (hdrs->ver >= 0x202) {
 
1337
                if (architecture == sun4u)
 
1338
                    kernel_params = (char *)((hdrs->bootstr_info_ptr_low - 0x400000) + 
 
1339
                                (image_base - 0x4000));
 
1340
                else
 
1341
                    kernel_params = (char *)(hdrs->bootstr_info_ptr_low & 0x3fffff);
 
1342
            }
 
1343
 
 
1344
            /* Some UltraAX machines have /dev/fd1 floppies only. */
 
1345
            if (floppyswap) {
 
1346
                char *s1;
 
1347
                
 
1348
                for (s1 = params; (s1 = strstr(s1, "root=/dev/fd0")) != NULL; s1 += 13)
 
1349
                        s1[12] = '1';
 
1350
            }
 
1351
 
 
1352
            if (initrd_string) {
 
1353
                char *q, *r, *initrd_device, *initrd_kname, *initrd_limit, *initrd_cur, c;
 
1354
                char *string;
 
1355
                int initrd_partno, len, statusok = 0;
 
1356
 
 
1357
                if (hdrs->ver >= 0x301)
 
1358
                        initrd_can_do_64bit_phys = 1;
 
1359
                
 
1360
                q = strchr (initrd_string, '|');
 
1361
                if (q && !initrd_size) {
 
1362
                    silo_fatal("When more than one initial ramdisk piece "
 
1363
                               "is specified, you have to give\n"
 
1364
                               "a non-zero initrd-size option which is no "
 
1365
                               "shorter than sum of all pieces\n"
 
1366
                               "lengths. Try again...\n");
 
1367
                    prom_halt ();
 
1368
                }
 
1369
                if (q) {
 
1370
                    initrd_start = memory_find ((initrd_size + 16383) & ~16383);
 
1371
                    if (!initrd_start) {
 
1372
                        silo_fatal("You do not have enough continuous "
 
1373
                                   "available memory for such initial "
 
1374
                                   "ramdisk.");
 
1375
                        prom_halt ();
 
1376
                    }
 
1377
                    string = strdup (initrd_string);
 
1378
                    q = strchr (string, '|');
 
1379
                    r = string;
 
1380
                    initrd_cur = initrd_start;
 
1381
                    initrd_limit = initrd_start + ((initrd_size + 16383) & ~16383);
 
1382
                    printf ("Loading parts of initial ramdisk...\n");
 
1383
                    for (;;) {
 
1384
                        c = *q;
 
1385
                        *q = 0;
 
1386
                        parse_name (r, initrd_defpart, &initrd_device, &initrd_partno, &initrd_kname);
 
1387
                        if (!initrd_kname) break;
 
1388
                        if (!initrd_device) initrd_device = initrd_defdevice;
 
1389
                        if (!silo_load_file(initrd_device, initrd_partno,
 
1390
                                            initrd_kname, (unsigned char *)initrd_cur,
 
1391
                                            (unsigned char *)initrd_limit, &len, 0, 0))
 
1392
                          break;
 
1393
                        initrd_cur += len;
 
1394
                        if (!c) {
 
1395
                            statusok = 1;
 
1396
                            break;
 
1397
                        }
 
1398
                        r = q + 1;
 
1399
                        q = strchr (r, '|');
 
1400
                        if (!q) q = strchr (r, 0);
 
1401
                        if (initrd_prompt) {
 
1402
                            silo_disk_close();
 
1403
                            printf ("Insert next media and press ENTER");
 
1404
                            prom_getchar ();
 
1405
                            printf ("\n");
 
1406
                        }
 
1407
                    }
 
1408
                    free (string);
 
1409
                    printf("Loaded initial ramdisk (%d bytes at 0x%x)...\n", (unsigned int)initrd_cur -
 
1410
                           (unsigned int)initrd_start, initrd_start);
 
1411
                    if (statusok) {
 
1412
                        extern unsigned long long sun4u_initrd_phys;
 
1413
                        extern unsigned long sun4m_initrd_pa;
 
1414
 
 
1415
                        if (architecture == sun4u) {
 
1416
                            if (initrd_can_do_64bit_phys) {
 
1417
                                hdrs->ramdisk_image64 = 
 
1418
                                        sun4u_initrd_phys + 0x400000ULL;
 
1419
                            } else {
 
1420
                                hdrs->ramdisk_image =
 
1421
                                        (unsigned int)sun4u_initrd_phys + 0x400000;
 
1422
                            }
 
1423
                        } else if (sun4m_initrd_pa) {
 
1424
                            hdrs->ramdisk_image = ((unsigned int)sun4m_initrd_pa);
 
1425
                        } else
 
1426
                            hdrs->ramdisk_image = ((unsigned int)initrd_start | 0xf0000000);
 
1427
 
 
1428
                        hdrs->ramdisk_size = initrd_size;
 
1429
                    } else
 
1430
                        printf ("Error: initial ramdisk loading failed. No initrd will be used.\n");
 
1431
                } else {
 
1432
                    parse_name (initrd_string, initrd_defpart, &initrd_device, &initrd_partno, &initrd_kname);
 
1433
                    if (initrd_kname) {
 
1434
                        if (!initrd_device) initrd_device = initrd_defdevice;
 
1435
                        if (silo_load_file(initrd_device, initrd_partno,
 
1436
                                           initrd_kname, (unsigned char *) 0x300000,
 
1437
                                           (unsigned char *) LARGE_RELOC,
 
1438
                                           0, 0, initrd_lenfunc)) {
 
1439
                            extern unsigned long long sun4u_initrd_phys;
 
1440
                            extern unsigned long sun4m_initrd_pa;
 
1441
 
 
1442
                            if (architecture == sun4u) {
 
1443
                                if (initrd_can_do_64bit_phys) {
 
1444
                                    hdrs->ramdisk_image64 =
 
1445
                                        sun4u_initrd_phys + 0x400000ULL;
 
1446
                                } else {
 
1447
                                    hdrs->ramdisk_image =
 
1448
                                        (unsigned int)sun4u_initrd_phys + 0x400000;
 
1449
                                }
 
1450
                            } else if (sun4m_initrd_pa) {
 
1451
                                hdrs->ramdisk_image = ((unsigned int)sun4m_initrd_pa);
 
1452
                            } else
 
1453
                                hdrs->ramdisk_image = ((unsigned int)initrd_start | 0xf0000000);
 
1454
 
 
1455
                            hdrs->ramdisk_size = initrd_size;
 
1456
                        }
 
1457
                    } else
 
1458
                        printf ("Error: initial ramdisk loading failed. No initrd will be used.\n");
 
1459
                }
 
1460
            }
 
1461
        }
 
1462
    } else {
 
1463
        char *p;
 
1464
        
 
1465
        if (off != 0 && !reboot)
 
1466
            memcpy (image_base, image_base + off, len);
 
1467
        p = seed_part_into_device (other_device, other_part);
 
1468
        strcpy (other_device, p);
 
1469
        params_device = other_device;
 
1470
    }
 
1471
 
 
1472
    silo_disk_close();
 
1473
    if (timer_status >= 1)
 
1474
        close_timer ();
 
1475
    if (proll) {
 
1476
        silo_set_prollargs(params, (unsigned int)image_base, len);
 
1477
        if (show_arguments) {
 
1478
            printf ("Arguments: \"%s\"\n");
 
1479
            pause_after = 1;
 
1480
        }
 
1481
    } else {
 
1482
        silo_set_bootargs(params, params_device);
 
1483
 
 
1484
        if (kernel_params) {
 
1485
            extern char barg_out[];
 
1486
            int len = *(unsigned int *)kernel_params;
 
1487
 
 
1488
            strncpy (kernel_params + 8, barg_out, len);
 
1489
            kernel_params [8 + len - 1] = 0;
 
1490
            *(unsigned int *)(kernel_params + 4) = 1;
 
1491
        }
 
1492
 
 
1493
        if (show_arguments) {
 
1494
            silo_show_bootargs();
 
1495
            pause_after = 1;
 
1496
        }
 
1497
    }
 
1498
 
 
1499
    if (pause_after) {
 
1500
        printf ("%s", pause_message);
 
1501
        prom_getchar ();
 
1502
        printf ("\n");
 
1503
    }
 
1504
 
 
1505
    memory_release();
 
1506
 
 
1507
    if (other && reboot) {
 
1508
        strcpy (sol_params, params_device);
 
1509
        strcat (sol_params, " ");
 
1510
        strcat (sol_params, params);
 
1511
        prom_reboot(sol_params);
 
1512
    }
 
1513
 
 
1514
    return ret_offset;
 
1515
}