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

« back to all changes in this revision

Viewing changes to silo/silo.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
/* silo - bootblock installation program
 
2
   
 
3
   Copyright (C) 1996 Maurizio Plaza
 
4
                 1996,98,99,2000 Jakub Jelinek
 
5
   
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 2 of the License, or
 
9
   (at your option) any later version.
 
10
   
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program; if not, write to the Free Software
 
18
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
 
19
   USA.  */
 
20
 
 
21
#if !defined(VERSION) || !defined(IMGVERSION)
 
22
#error VERSION and IMGVERSION must be defined
 
23
#endif
 
24
#define DFL_CONFIG "/etc/silo.conf"
 
25
#define DFL_BACKUP "/boot/old.b"
 
26
#define DFL_PRIMARY "/boot/first.b"
 
27
#define DFL_PRIMARY_U "/boot/ultra.b"
 
28
#define DFL_SECONDARY "/boot/second.b"
 
29
 
 
30
#ifdef __sun__
 
31
#include "../second/fs/ufs.c"
 
32
#endif
 
33
 
 
34
#include <errno.h>
 
35
#include <stdio.h>
 
36
#include <stdarg.h>
 
37
#include <string.h>
 
38
#include <stdlib.h>
 
39
#include <features.h>
 
40
#include <unistd.h>
 
41
#include <sys/ioctl.h>
 
42
#ifdef __GLIBC__
 
43
#  include <sys/stat.h>
 
44
#  include <sys/types.h>
 
45
#  include <sys/time.h>
 
46
#  define _LINUX_STAT_H
 
47
#  define _LINUX_VFS_H
 
48
#  define _LINUX_TIME_H
 
49
#  define _LINUX_STRING_H_
 
50
#endif
 
51
#ifdef __linux__
 
52
#  include <linux/fs.h>
 
53
#  include <ext2fs/ext2_fs.h>
 
54
#  include <ext2fs/ext2fs.h>
 
55
#  include <scsi/scsi.h>
 
56
#  include <sys/vfs.h>
 
57
#  ifdef __GLIBC__
 
58
#    include <sys/sysmacros.h>
 
59
#    define mmajor(x) major(x)
 
60
#    define mminor(x) minor(x)
 
61
#    define mmakedev(x,y) makedev(x,y)
 
62
#  else
 
63
#    define mmajor(x) (int)((x) >> 8)
 
64
#    define mminor(x) (int)((x) & 0xff)
 
65
#    define mmakedev(major, minor) (((major) << 8) | (minor))
 
66
#  endif
 
67
#  include <md-int.h>
 
68
#elif defined (__sun__)
 
69
#  include <sys/types.h>
 
70
#  include <sys/stat.h>
 
71
#  include <non-linux/ext2_fs.h>
 
72
#  include <ext2fs/ext2fs.h>
 
73
#  include "ufs.h"
 
74
#  include <limits.h>
 
75
struct hwdevice;
 
76
static int ufs_blocks (struct hwdevice *, ino_t);
 
77
#else
 
78
#  error "Unknown system"
 
79
#endif
 
80
#include <fcntl.h>
 
81
#include <sys/stat.h>
 
82
#include <sys/utsname.h>
 
83
#include <dirent.h>
 
84
#include <ctype.h>
 
85
#include "floppy.h"
 
86
#ifndef __intel__
 
87
#include "prom.h"
 
88
#endif
 
89
#include "../first/first.h"
 
90
#include "../first/ultra.h"
 
91
#include "../first/fd.h"
 
92
#include "../first/ieee32.h"
 
93
 
 
94
#define DIGIT_OFFSET (DIGIT_OFFSET_TMP + 0x223)
 
95
#define LETTER_OFFSET (LETTER_OFFSET_TMP + 0x223)
 
96
#define NUMBER_OFFSET (NUMBER_OFFSET_TMP + 0x223)
 
97
#define ULTRA_LETTER_OFFSET (ULTRA_LETTER_OFFSET_TMP + 0x223)
 
98
#define ULTRA_NUMBER_OFFSET (ULTRA_NUMBER_OFFSET_TMP + 0x223)
 
99
#define FD_DIGIT_OFFSET (FD_DIGIT_OFFSET_TMP + 0x223)
 
100
#define FD_LETTER_OFFSET (FD_LETTER_OFFSET_TMP + 0x223)
 
101
 
 
102
/* Checks our config file for errors */
 
103
int confcheck(char*);
 
104
char *cfg_get_strg (char *, char *);
 
105
int cfg_get_flag (char *, char *);
 
106
static int allow_confchk_fail = 0;
 
107
 
 
108
/* This is just so that we don't have to fight with incompatible ufs_fs.h headers */
 
109
#define SILO_UFS_MAGIC 0x00011954
 
110
struct silo_ufs_super_block {
 
111
        unsigned char xxx1[36];
 
112
        unsigned int fs_fsize;
 
113
        unsigned char xxx2[1332];
 
114
        unsigned int fs_magic;
 
115
};
 
116
                                
 
117
struct sun_disklabel {
 
118
    unsigned char info[128];    /* Informative text string */
 
119
    unsigned char spare[292];   /* Boot information etc. */
 
120
    unsigned short rspeed;      /* Disk rotational speed */
 
121
    unsigned short pcylcount;   /* Physical cylinder count */
 
122
    unsigned short sparecyl;    /* extra sects per cylinder */
 
123
    unsigned char spare2[4];    /* More magic... */
 
124
    unsigned short ilfact;      /* Interleave factor */
 
125
    unsigned short ncyl;        /* Data cylinder count */
 
126
    unsigned short nacyl;       /* Alt. cylinder count */
 
127
    unsigned short ntrks;       /* Tracks per cylinder */
 
128
    unsigned short nsect;       /* Sectors per track */
 
129
    unsigned char spare3[4];    /* Even more magic... */
 
130
    struct sun_partition {
 
131
        unsigned long start_cylinder;
 
132
        unsigned long num_sectors;
 
133
    } partitions[8];
 
134
    unsigned short magic;       /* Magic number */
 
135
    unsigned short csum;        /* Label xor'd checksum */
 
136
};
 
137
 
 
138
enum typeenum { TYPE_UNKNOWN, TYPE_SCSI, TYPE_IDE };
 
139
 
 
140
struct hwdevice {
 
141
    char *wholedev;
 
142
    char *dev;
 
143
    enum typeenum type;
 
144
    int id;
 
145
    int part;
 
146
    int partat0;
 
147
    unsigned char nsect;
 
148
    unsigned short bs;
 
149
    unsigned long doff;
 
150
    __u32 blocks[512];
 
151
    struct hwdevice *next;
 
152
} *hwdevs = NULL;
 
153
 
 
154
__u32 swab32 (__u32 value)
 
155
{
 
156
    return ((value >> 24) | ((value >> 8) & 0xff00) |
 
157
            ((value << 8) & 0xff0000) | (value << 24));
 
158
}
 
159
 
 
160
__u16 swab16 (__u16 value)
 
161
{
 
162
    return (value >> 8) | (value << 8);
 
163
}
 
164
#define bswab32(x) (x)
 
165
#define bswab16(x) (x)
 
166
 
 
167
int ultra = 0;
 
168
int prombug = 1; /* Number of gigabytes PROM is able to boot from. if ultra, it is always inf. */
 
169
int raid1 = 0;
 
170
int second_b_len;
 
171
int masterboot = 1;
 
172
int floppy_image = 0;           /* Calculate cross checksums. */
 
173
char *flash_image = NULL;       /* Open this and calculate flash checksum. */
 
174
char *first, *second, *old;     /* File names */
 
175
int promver = -1;
 
176
int oldroot = -1;
 
177
enum fs_type { unknownfs, ext2fs, ufsfs, romfs } fstype = unknownfs;
 
178
 
 
179
static void silo_fatal(char *fmt,...)
 
180
{
 
181
    va_list ap;
 
182
    va_start (ap, fmt);
 
183
    fprintf (stderr, "Fatal error: ");
 
184
    vfprintf (stderr, fmt, ap);
 
185
    putc ('\n', stderr);
 
186
    va_end (ap);
 
187
    exit (1);
 
188
}
 
189
 
 
190
int devopen (const char *name, int flags)
 
191
{
 
192
    int fd = open (name, flags);
 
193
    if (fd < 0 && errno == ENOENT) {
 
194
        if (oldroot != -1) {
 
195
            fchdir(oldroot);
 
196
            if (*name == '/') name++;
 
197
            fd = open (name, flags);
 
198
            chdir("/");
 
199
        }
 
200
    }
 
201
    return fd;
 
202
}
 
203
 
 
204
int check_fs (int fd)
 
205
{
 
206
    struct silo_ufs_super_block ufs;
 
207
    struct ext2_super_block sb; /* Super Block Info */
 
208
    struct romfs_super_block {
 
209
        __u32 word0;
 
210
        __u32 word1;
 
211
        __u32 size;
 
212
        __u32 checksum;
 
213
    } rsd;
 
214
 
 
215
    if (lseek (fd, 1024, 0) != 1024 || read (fd, &sb, sizeof (sb)) != sizeof (sb))
 
216
        silo_fatal("Cannot read Super Block!");
 
217
    if (swab16 (sb.s_magic) == EXT2_SUPER_MAGIC) {
 
218
        if (fstype == unknownfs) fstype = ext2fs;
 
219
        return 1024 << swab32 (sb.s_log_block_size);
 
220
    }
 
221
    if (lseek (fd, 0, 0) != 0 || read (fd, &rsd, sizeof(rsd)) != sizeof (rsd))
 
222
        return -1;
 
223
    if (!strncmp ((char *)&rsd, "-rom1fs-", 8)) {
 
224
        if (fstype == unknownfs) fstype = romfs;
 
225
        return 512;
 
226
    }
 
227
    if (lseek (fd, 8192, 0) != 8192 || read (fd, &ufs, sizeof (ufs)) != sizeof (ufs))
 
228
        return -1;
 
229
    if (bswab32 (ufs.fs_magic) == SILO_UFS_MAGIC) {
 
230
        if (fstype == unknownfs) fstype = ufsfs;
 
231
        return ufs.fs_fsize;
 
232
    }
 
233
    return -1;
 
234
}
 
235
 
 
236
void read_sb (struct hwdevice *hwdev)
 
237
{
 
238
    int fd;
 
239
    char buff[512];
 
240
    struct sun_disklabel *sdl;
 
241
    char *p;
 
242
    int i;
 
243
 
 
244
    hwdev->partat0 = 0;
 
245
    if ((fd = devopen ((char *)hwdev->dev, O_RDONLY)) == -1)
 
246
        silo_fatal("Cannot open superblock on %s", hwdev->dev);
 
247
    hwdev->bs = check_fs (fd);
 
248
    if (hwdev->bs == (unsigned short)-1)
 
249
        silo_fatal("File systems other than ext2, ext3, ufs and romfs "
 
250
                   "not yet supported", hwdev->dev);
 
251
    close (fd);
 
252
    hwdev->nsect = hwdev->bs / 512;
 
253
    if (hwdev->part == -1)
 
254
        return;
 
255
    sdl = (struct sun_disklabel *) &buff;
 
256
    if ((fd = devopen (hwdev->wholedev, O_RDONLY)) == -1)
 
257
        silo_fatal("Error opening %s", hwdev->wholedev);
 
258
    if (read (fd, buff, sizeof (buff)) != sizeof (buff))
 
259
        silo_fatal("Error reading %s's label", hwdev->wholedev);
 
260
    for (i = 0; i < 8; i++) {
 
261
        if (i == 2) continue;
 
262
        if (!sdl->partitions[i].start_cylinder && sdl->partitions[i].num_sectors) {
 
263
            hwdev->partat0 = i;
 
264
#ifdef __linux__
 
265
            p = strchr (hwdev->wholedev, 0);
 
266
            *p++ = '1' + hwdev->partat0;
 
267
            *p = 0;
 
268
#endif
 
269
            break;
 
270
        }
 
271
    }
 
272
    if (i == 8 && !sdl->partitions[2].start_cylinder && sdl->partitions[2].num_sectors) {
 
273
        i = 2;
 
274
        hwdev->partat0 = 2;
 
275
#ifdef __linux__
 
276
        p = strchr (hwdev->wholedev, 0);
 
277
        *p++ = '1' + hwdev->partat0;
 
278
        *p = 0;
 
279
#endif
 
280
    }
 
281
    if (i == 8) {
 
282
        for (i = 0; i < 8; i++) {
 
283
            if (!sdl->partitions[i].start_cylinder) {
 
284
                hwdev->partat0 = i;
 
285
                break;
 
286
            }
 
287
        }
 
288
    }
 
289
    if (i == 8) {
 
290
        silo_fatal("In order to install SILO you must start at least "
 
291
                   "one partition on cylinder\n"
 
292
                   "0. Consider setting %s3 as WHOLE_DISK (starting at 0 "
 
293
                   "and ending at disk end)\n"
 
294
                   "and %s1 starting on cylinder 0 (both will make your "
 
295
                   "life easier)\n", hwdev->wholedev, hwdev->wholedev);
 
296
    }
 
297
    hwdev->doff = bswab16(sdl->ntrks) * bswab16(sdl->nsect) * bswab32(sdl->partitions[hwdev->part].start_cylinder);
 
298
    close (fd);
 
299
}
 
300
 
 
301
#define SECOND_B_TEMPL "%s___@#$%d___"
 
302
 
 
303
void gpb_cleanup(char *filename, int n)
 
304
{
 
305
    char buffer[1024];
 
306
    int i;
 
307
    
 
308
    for (i = 1; i <= n; i++) {
 
309
        sprintf (buffer, SECOND_B_TEMPL, filename, i);
 
310
        unlink (buffer);
 
311
    }
 
312
}
 
313
 
 
314
void make_room_for_raid1 (struct hwdevice *hwdev, char *name)
 
315
{
 
316
    char buf[512];
 
317
    int len, i;
 
318
    int fd;
 
319
    struct stat st;
 
320
 
 
321
    if (raid1 <= 1)
 
322
        return;
 
323
    if ((fd = open (name, O_RDWR)) == -1)
 
324
        silo_fatal("Cannot open %s", name);
 
325
    if (fstat (fd, &st) < 0)
 
326
        silo_fatal("Couldn't stat %s", name);
 
327
    if (lseek (fd, 0x90c, 0) != 0x90c || read(fd, buf, 12) != 12)
 
328
        silo_fatal("Could not read %s version and length header", name);
 
329
    if (memcmp (buf, "SILO", 4))
 
330
        silo_fatal("Second stage %s too old", name);
 
331
    len = *(int *)&buf[8];
 
332
    if (len % 512 || st.st_size < len || (st.st_size - len) % 2048)
 
333
        silo_fatal("Second stage %s has wrong size", name);
 
334
    i = raid1 - 1 - (st.st_size - len) / 2048;
 
335
    if (i > 0) {
 
336
        if (lseek (fd, len, 0) != len)
 
337
            silo_fatal("Could not seek in %s", name);
 
338
        memset(buf, 0, 512);
 
339
        /* Should not use ftruncate here, because we cannot have fs
 
340
           holes in */
 
341
        for (i = 4 * i; i > 0; i--) {
 
342
            if (write (fd, buf, 512) != 512)
 
343
                silo_fatal("Could not write to %s", name);
 
344
        }
 
345
    }
 
346
    second_b_len = len;
 
347
    close (fd);
 
348
}
 
349
 
 
350
int get_partition_blocks (struct hwdevice *hwdev, char *filename)
 
351
{
 
352
    int fd;
 
353
    int block, i, j, k;
 
354
    struct stat st;
 
355
    int movecount = 0;
 
356
    char buffer[1024];
 
357
    char *name = filename;
 
358
    char *buf = NULL;
 
359
    int size = 0;
 
360
    
 
361
again:
 
362
    if ((fd = open (name, O_RDONLY)) == -1) {
 
363
        gpb_cleanup(filename, movecount);
 
364
        silo_fatal("Cannot find %s", name);
 
365
    }
 
366
    if (fstat (fd, &st) < 0) {
 
367
        gpb_cleanup(filename, movecount);
 
368
        silo_fatal("Couldn't stat %s", name);
 
369
    }
 
370
#ifdef __linux__
 
371
    if (!movecount)
 
372
        size = st.st_size;
 
373
    if (fstype == romfs) {
 
374
        char *p = strrchr (name, '/');
 
375
        long start;
 
376
        if (p) p++; else p = name;
 
377
        start = (long)st.st_ino + 16 + ((strlen(p) + 16) & ~15);
 
378
        if (start & 511)
 
379
                silo_fatal("File %s on romfs not aligned on 512B boundary. "
 
380
                           "Use genromfs -a to generate the image", name);
 
381
        start = hwdev->doff + start / 512;
 
382
        if (flash_image) start += 1024 / 512;   /* make room for ieee32 */
 
383
        for (j = 0; j * 512 < size; j++)
 
384
                hwdev->blocks[j] = start + j;
 
385
        hwdev->blocks[j] = 0;
 
386
        close(fd);
 
387
        return 0;
 
388
    }
 
389
    for (i = 0, j = 0;; i++) {
 
390
        block = i;
 
391
        if ((j << 9) >= size || ioctl (fd, FIBMAP, &block) < 0)
 
392
            break;
 
393
        if (!block) {
 
394
            if ((j << 9) < size)
 
395
                silo_fatal("Filesystem holes are not yet supported for "
 
396
                           "second stage loader. Mail "
 
397
                           "silo-general@lists.sparc-boot.org");
 
398
            else
 
399
                break;
 
400
        }
 
401
        if (prombug && block * hwdev->nsect + hwdev->doff >= 0x200000 * prombug) {
 
402
            if (movecount < 5) {
 
403
                if (!movecount) {
 
404
                        if (hwdev->id)
 
405
                                silo_fatal("Your %s is located above the "
 
406
                                           "magic %dGB boundary from the "
 
407
                                           "start of the disk\n"
 
408
                                           "on one of the RAID1 mirrors. "
 
409
                                           "Please make sure it is below the "
 
410
                                           "limit on all\n"
 
411
                                           "mirrors.", filename, prombug);
 
412
                        buf = malloc (size);
 
413
                        if (!buf)
 
414
                                silo_fatal("Not enough memory");
 
415
                        if (read (fd, buf, size) != size)
 
416
                                silo_fatal("Cannot read from %s", filename);
 
417
                }
 
418
                close (fd);
 
419
                movecount++;
 
420
                sprintf (buffer, SECOND_B_TEMPL, filename, movecount);
 
421
                name = buffer;
 
422
                fd = creat (name, 0644);
 
423
                if (!fd || write (fd, buf, size) != size) {
 
424
                        gpb_cleanup(filename, movecount);
 
425
                        silo_fatal("Your %s is located above the magic %dGB "
 
426
                                   "boundary from the start of the disk.\n"
 
427
                                   "Please move it down, so that SILO first "
 
428
                                   "stage loader can load it.",
 
429
                                   filename, prombug);
 
430
                }
 
431
                close (fd);
 
432
                goto  again;
 
433
            }
 
434
            gpb_cleanup(filename, movecount);
 
435
            silo_fatal("Your %s is located above the magic %dGB boundary "
 
436
                       "from the start of the disk.\n"
 
437
                   "Please move it down, so that SILO first stage loader can load it.", filename, prombug);
 
438
        }
 
439
        for (k = 0; k < hwdev->nsect; k++)
 
440
            hwdev->blocks[j++] = block * hwdev->nsect + hwdev->doff + k;
 
441
    }
 
442
    hwdev->blocks[j] = 0;
 
443
    if (raid1 > 1) {
 
444
        if (hwdev->id) {
 
445
            if (!masterboot) {
 
446
                /* As current RAID1 does not reserve any space for bootblocks, non-masterboot
 
447
                   would resync away the bootblock unless second.b starts on exactly the same
 
448
                   offsets in each device */
 
449
                if (memcmp (hwdevs->blocks, hwdev->blocks, sizeof(hwdev->blocks)))
 
450
                        silo_fatal("With silo -t on RAID1 all mirrors must "
 
451
                                   "start at the same offset\n"
 
452
                                   "from the start of the disk.");
 
453
            } else
 
454
                for (i = 0; i < 4; i++)
 
455
                    hwdev->blocks[i] = hwdev->blocks[second_b_len / 512 + (hwdev->id - 1) * 4 + i];
 
456
        }
 
457
    }
 
458
    if (buf) free (buf);
 
459
    if (movecount) {
 
460
        if (rename (name, filename) < 0) {
 
461
            gpb_cleanup(filename, movecount - 1);
 
462
            silo_fatal("Cannot rename a suitably located copy (below 1GB "
 
463
                       "from start of disk) of %s to it's old position.\n"
 
464
                       "Please check %s\n", filename, filename);
 
465
        }
 
466
        gpb_cleanup(filename, movecount - 1);
 
467
    }
 
468
#elif defined(__sun__)
 
469
    ufs_blocks (hwdev, st.st_ino);
 
470
#endif
 
471
    close (fd);
 
472
    return 0;
 
473
}
 
474
 
 
475
char *new_root = NULL;
 
476
 
 
477
void write_block_device (struct hwdevice *hwdev)
 
478
{
 
479
    int fd, rc;
 
480
    int offset, off;
 
481
    __u32 tmp;
 
482
    unsigned char part;
 
483
 
 
484
    if ((fd = devopen (masterboot ? hwdev->wholedev : hwdev->dev,
 
485
                       O_RDWR)) == -1)
 
486
        silo_fatal("Cannot open %s", hwdev->dev);
 
487
    if (flash_image) off = IEEE32_OFFSET;
 
488
    else if (floppy_image) off = 1020 + 512 - 4;
 
489
    else off = 1020;
 
490
    if (lseek (fd, off, SEEK_SET) != off)
 
491
        silo_fatal("Seek error on %s", hwdev->dev);
 
492
    if (floppy_image) {
 
493
        int j;
 
494
        for (j = 0; j < 512 && hwdev->blocks[j]; j++);
 
495
        j *= 512;
 
496
        tmp = bswab32 (j);
 
497
        rc = write (fd, &tmp, 4);
 
498
        if (rc != 4)
 
499
            silo_fatal("Couldn't write to %s", hwdev->dev);
 
500
    }
 
501
    tmp = bswab32 (hwdev->blocks[0]);
 
502
    rc = write (fd, &tmp, 4);
 
503
    if (rc != 4)
 
504
        silo_fatal("Couldn't write to %s", hwdev->dev);
 
505
    if (!flash_image) {
 
506
        if (!ultra || floppy_image) {
 
507
            if (floppy_image)
 
508
                offset = FD_DIGIT_OFFSET;
 
509
            else
 
510
                offset = DIGIT_OFFSET;
 
511
            if (lseek (fd, offset, SEEK_SET) != offset)
 
512
                silo_fatal("Seek error on %s", hwdev->dev);
 
513
            part = hwdev->partat0 + '0';
 
514
            rc = write (fd, &part, 1);
 
515
            if (rc != 1)
 
516
                silo_fatal("Couldn't write to %s", hwdev->dev);
 
517
        }
 
518
        if (floppy_image)
 
519
            offset = FD_LETTER_OFFSET;
 
520
        else if (ultra)
 
521
            offset = ULTRA_LETTER_OFFSET;
 
522
        else
 
523
            offset = LETTER_OFFSET;
 
524
        if (lseek (fd, offset, SEEK_SET) != offset)
 
525
            silo_fatal("Seek error on %s", hwdev->dev);
 
526
        part = hwdev->partat0 + 'a';
 
527
        rc = write (fd, &part, 1);
 
528
        if (rc != 1)
 
529
            silo_fatal("Couldn't write to %s", hwdev->dev);
 
530
        if (!floppy_image) {
 
531
            if (ultra)
 
532
                offset = ULTRA_NUMBER_OFFSET;
 
533
            else
 
534
                offset = NUMBER_OFFSET;
 
535
            if (lseek (fd, offset, SEEK_SET) != offset)
 
536
                silo_fatal("Seek error on %s", hwdev->dev);
 
537
            part = 0;
 
538
            if (raid1)
 
539
                part = hwdev->id + 1;
 
540
            rc = write (fd, &part, 1);
 
541
            if (rc != 1)
 
542
                silo_fatal("Couldn't write to %s", hwdev->dev);
 
543
        }
 
544
    }
 
545
    close (fd);
 
546
}
 
547
 
 
548
void write_block_tables (struct hwdevice *hwdev, char *filename, char *config_file, int partno)
 
549
{
 
550
    int fd, rc, i;
 
551
    struct {
 
552
        unsigned char l;
 
553
        unsigned char partno;
 
554
        unsigned char partat0;
 
555
        unsigned char raid_dsk_number;
 
556
        char silo_conf[256];
 
557
        unsigned char silover[8];
 
558
        unsigned int len;
 
559
        unsigned char partnos[32];
 
560
        unsigned char partat0s[32];
 
561
    } buffer;
 
562
    int tordonly = 0;
 
563
    struct hwdevice *d;
 
564
 
 
565
    if ((fd = open (filename, O_RDWR)) == -1) {
 
566
        if (raid1)
 
567
            silo_fatal("Cannot open %s", filename);
 
568
        if ((fd = open (filename, O_RDONLY)) >= 0) {
 
569
            close (fd); /* Maybe it is romfs */
 
570
            if ((fd = devopen (hwdev->wholedev, O_RDWR)) == -1)
 
571
                silo_fatal("Cannot open %s", hwdev->wholedev);
 
572
            tordonly = 1;
 
573
        } else
 
574
            silo_fatal("Cannot open %s", filename);
 
575
    }
 
576
    if (tordonly) {
 
577
        char *p = (char *)hwdev->blocks, *pend = p + sizeof (hwdev->blocks);
 
578
 
 
579
        if (raid1)
 
580
            silo_fatal("RAID1 not supported with read-only filesystems");
 
581
        for (i = 0, rc = 0; p < pend; i++, p+=512) {
 
582
            if (lseek (fd, hwdev->blocks [i] * 512, SEEK_SET) != hwdev->blocks [i] * 512)
 
583
                silo_fatal("Cannot seek in %s", filename);
 
584
            rc += write (fd, p, 512);
 
585
        }
 
586
    } else {
 
587
        if (lseek (fd, 0, SEEK_SET) != 0)
 
588
            silo_fatal("Cannot seek in %s", filename);
 
589
        rc = write (fd, hwdev->blocks, sizeof (hwdev->blocks));
 
590
        if (raid1 > 1) {
 
591
            if (rc != sizeof (hwdev->blocks))
 
592
                silo_fatal("Couldn't write to %s", filename);
 
593
            if (lseek (fd, second_b_len, SEEK_SET) != second_b_len)
 
594
                silo_fatal("Cannot seek in %s", filename);
 
595
            for (d = hwdev->next; d; d = d->next)
 
596
                rc = write (fd, d->blocks, sizeof (d->blocks));
 
597
        }
 
598
    }
 
599
    if (rc != sizeof (hwdev->blocks))
 
600
        silo_fatal("Couldn't write to %s", filename);
 
601
    if (tordonly)
 
602
        i = hwdev->blocks [0x808/512] * 512 + 0x808 % 512;
 
603
    else
 
604
        i = 0x808;
 
605
    if (lseek (fd, i, SEEK_SET) != i)
 
606
        silo_fatal("Cannot seek in %s", filename);
 
607
    if (read (fd, &buffer, sizeof(buffer)) != sizeof(buffer))
 
608
        silo_fatal("Couldn't read from %s", filename);
 
609
    if (lseek (fd, i, SEEK_SET) != i)
 
610
        silo_fatal("Cannot seek in %s", filename);
 
611
    if (buffer.l != 'L' || memcmp(buffer.silover, "SILO", 4))
 
612
        silo_fatal("Corrupted %s or second stage with incorrect version",
 
613
                   filename);
 
614
    buffer.partno = partno;
 
615
    buffer.partat0 = hwdev->partat0;
 
616
    buffer.raid_dsk_number = 0;
 
617
    strncpy (buffer.silo_conf, config_file, 255);
 
618
    buffer.silo_conf[255] = 0;
 
619
    if (raid1) {
 
620
        for (d = hwdev; d; d = d->next) {
 
621
            buffer.partnos[d->id] = d->part + 1;
 
622
            buffer.partat0s[d->id] = d->partat0;
 
623
        }
 
624
    }
 
625
    if (write (fd, &buffer, sizeof(buffer)) != sizeof(buffer))
 
626
        silo_fatal("Couldn't write to %s", filename);
 
627
    close (fd);
 
628
    for (d = hwdev; d; d = d->next)
 
629
        write_block_device (d);
 
630
}
 
631
 
 
632
void usage (char *s)
 
633
{
 
634
    fprintf (stderr,
 
635
            "SILO " VERSION " Sparc Improved boot LOader\n"
 
636
            "Usage: %s [options]\n"
 
637
            "Options:\n"
 
638
            " -r root_path   chroots into root_path (all paths relative to this)\n"
 
639
            " -b secondary   use secondary as second stage loader instead of /boot/second.b\n"
 
640
            " -i primary     install primary as first stage loader (instead of\n"
 
641
            "                /boot/first.b). If -i is specified, your boot block will be\n"
 
642
            "                always overwritten (by default only if it is not SILO or has\n"
 
643
            "                wrong version)\n"
 
644
            " -C config      specify alternate config file instead of /etc/silo.conf\n"
 
645
            "                (your config file has to reside on the same physical disk as\n"
 
646
            "                secondary - perhaps on different partitions - on that disk's\n"
 
647
            "                bootblock will be primary installed)\n"
 
648
            " -S backup      force saving your old bootblock into backup\n"
 
649
            " -s backup      save your old bootblock only if backup doesn't exist yet\n"
 
650
            " -p 0|2         force prom version to be 0 or 2 (default is auto-detection)\n"
 
651
            " -t             store bootblock on the same partition as second stage loader\n"
 
652
            "                (default is into the bootblock of the whole disk)\n"
 
653
            " -f             force overwriting of bootblock\n"
 
654
            " -V             show version\n"
 
655
            " -v             print your PROM major version (0 or 2) and exit\n"
 
656
            " -u             force v9 (ultrasparc) target, even on v8\n"
 
657
            " -U             force v8 target, even on v9\n"
 
658
            " -F             make a romfs bootable floppy\n"
 
659
            " -J image       make a romfs bootable flash image\n"
 
660
            "                -J and -F are incompatible\n"
 
661
            " -a             Allow silo.conf syntax check to fail\n"
 
662
            ,s);
 
663
    exit (1);
 
664
}
 
665
 
 
666
int examine_bootblock (char *device, char *filename, int do_backup)
 
667
{
 
668
    char buffer[512 * 15];
 
669
    int fd, rc;
 
670
    FILE *fp;
 
671
    int ret = 0;
 
672
 
 
673
    if ((fd = devopen (device, O_RDONLY)) == -1)
 
674
        silo_fatal("Cannot open %s", device);
 
675
    if (lseek (fd, 512, 0) != 512)
 
676
        silo_fatal("Couldn't seek on %s", device);
 
677
    if (read (fd, buffer, sizeof (buffer)) != sizeof(buffer))
 
678
        silo_fatal("Couldn't read your old bootblock");
 
679
    close (fd);
 
680
    if (memcmp (buffer + 24, "SILO" IMGVERSION, 8))
 
681
        ret = 1;
 
682
 
 
683
    if (do_backup) {
 
684
        if ((fp = fopen (filename, "w")) == NULL) {
 
685
            if (do_backup >= 2)
 
686
                return ret;
 
687
            silo_fatal("Cannot open file for saving backup of your bootblock");
 
688
        }
 
689
        if ((rc = fwrite (buffer, 1, sizeof (buffer), fp)) != sizeof (buffer))
 
690
            silo_fatal("Couldn't write to %s backup of your bootblock",
 
691
                       filename);
 
692
        fclose (fp);
 
693
    }
 
694
    return ret;
 
695
}
 
696
 
 
697
void flash_check_sum (char *data, unsigned int dsize)
 
698
{
 
699
    unsigned int sum;
 
700
 
 
701
    for (sum = 0; dsize-- != 0; data++)
 
702
        sum += *((unsigned char *)data);
 
703
 
 
704
    data[0] = sum >> 24;
 
705
    data[1] = sum >> 16;
 
706
    data[2] = sum >> 8;
 
707
    data[3] = sum;
 
708
}
 
709
 
 
710
void install_first_stage (char *device, char *filename)
 
711
{
 
712
    char buff[1024];
 
713
    int rc;
 
714
    int fd;
 
715
    FILE *fp;
 
716
    struct sun_disklabel sdl;
 
717
 
 
718
    if ((fd = devopen (device, floppy_image ? O_RDWR : O_WRONLY)) == -1)
 
719
        silo_fatal("Couldn't open device %s for writing", device);
 
720
    if ((fp = fopen (filename, "r")) == NULL)
 
721
        silo_fatal("Couldn't open file %s", filename);
 
722
    rc = fread (buff, 1, (floppy_image || flash_image) ? 1024 : 512, fp);
 
723
    if (rc <= 0)
 
724
        silo_fatal("Couldn't read new silo bootblock from %s", filename);
 
725
    if (floppy_image) {
 
726
        unsigned short *ush;
 
727
        unsigned short x;
 
728
        unsigned int s, d;
 
729
        int i;
 
730
 
 
731
        if (lseek (fd, 0, 0))
 
732
                silo_fatal("Couldn't seek on %s", device);
 
733
        if (read(fd, (char *)&sdl, 512) != 512)
 
734
                silo_fatal("Couldn't read on %s", device);
 
735
        if (lseek (fd, 0, 0))
 
736
                silo_fatal("Couldn't seek on %s", device);
 
737
        if (strncmp ((char *)&sdl, "-rom1fs-", 8))
 
738
                silo_fatal("Couldn't find romfs image on %s", device);
 
739
        memcpy (((char *)&sdl) + 128, floppy_label + 128, 512 - 128);
 
740
        ush = (unsigned short *)&sdl;
 
741
 
 
742
        /* This is a bit difficult, since we have to make two checksums right:
 
743
           partition table expects xor of all u16 in the first 512 bytes to be 0,
 
744
           romfs expects sum of all u32 in the first 512 bytes to be 0.
 
745
           Algorithm written by Gert-jan Los (los@lsdb.bwl.uni-mannheim.de). */
 
746
        sdl.csum = 0xdead; /* Could be zero... */
 
747
        ush[6] = 0; ush[7] = 0;
 
748
        memset (ush + 60, 0, 8);
 
749
        for (i = 0, d = 0; i < 256; i+=2)
 
750
                d += *(unsigned int *)(ush + i);
 
751
        for (i = 0, x = 0; i < 256; i++)
 
752
                x ^= ush[i];
 
753
        if (d & 1)
 
754
                s = (x ^ 1) << 16 ^ 1;
 
755
        else
 
756
                s = x << 16;
 
757
        *(unsigned int *)(ush + 6) = s;
 
758
        d += s;
 
759
        *(unsigned int *)(ush + 60) = (-d/2);
 
760
        *(unsigned int *)(ush + 62) = (-d/2);
 
761
 
 
762
        if (write (fd, &sdl, 512) != 512)
 
763
            silo_fatal("Couldn't write new partition table to %s", device);
 
764
    } else if (flash_image) {
 
765
        /*
 
766
         * Make sure that both block table address and checksum fit.
 
767
         */
 
768
        if (rc > 1016)
 
769
            silo_fatal("Flash bootblock is too large");
 
770
        /*
 
771
         * Here we do an assumption which is not quite safe.
 
772
         * PROM gets the size looking at section headers,
 
773
         * we use the file size for that. If there is any padding,
 
774
         * these sizes will diverge. So far everything was ok.
 
775
         */
 
776
        flash_check_sum (buff, rc);
 
777
        rc += 4;
 
778
    } else if (lseek (fd, 512, 0) != 512)
 
779
        silo_fatal("Couldn't seek on %s", device);
 
780
    if (write (fd, buff, rc) != rc)
 
781
        silo_fatal("Couldn't write new silo bootblock to %s", device);
 
782
    close (fd);
 
783
    fclose (fp);
 
784
}
 
785
 
 
786
int get_prom_ver(int use_prom)
 
787
{
 
788
#if defined(__linux__)
 
789
    FILE *f = fopen("/proc/cpuinfo","r");
 
790
    int ver = -1;
 
791
    char buffer[1024];
 
792
    char *p;
 
793
 
 
794
    if (f) {
 
795
        while (fgets(buffer, 1024, f)) {
 
796
            if (!strncmp (buffer, "promlib", 7)) {
 
797
                p = strstr (buffer, "Version ");
 
798
                if (p) {
 
799
                    p += 8;
 
800
                    if (*p == '0' || (*p >= '2' && *p <= '3')) {
 
801
                        ver = *p - '0';
 
802
                    }
 
803
                }
 
804
            } else if (!strncmp (buffer, "prom", 4) &&
 
805
                       isspace(buffer[4])) {
 
806
                p = strchr (buffer, ':');
 
807
                if (p) {
 
808
                    p++;
 
809
                    while (isspace (*p)) p++;
 
810
                    switch (*p) {
 
811
                    case '2': if (p[1] == '.' && isdigit(p[2]) &&
 
812
                                  (p[2] >= '6' || isdigit(p[3])))
 
813
                                prombug = 2; break;
 
814
                    case '3': prombug = 0; break;
 
815
                    }
 
816
                }
 
817
            }
 
818
        }
 
819
    }
 
820
    return ver;
 
821
#elif defined(__sun__)
 
822
    int ver = -1;
 
823
    
 
824
    if (use_prom)
 
825
        ver = prom_getversion ();
 
826
    return ver;
 
827
#endif
 
828
}
 
829
 
 
830
/* Canonicalize path, and return a new path. Do everything in situ.
 
831
   The new path differs from path in:
 
832
        Multiple `/'s are collapsed to a single `/'.
 
833
        Leading `./'s and trailing `/.'s are removed.
 
834
        Trailing `/'s are removed.
 
835
        Non-leading `../'s and trailing `..'s are handled by removing
 
836
        portions of the path. */
 
837
char *canonicalize_pathname (char *path)
 
838
{
 
839
    int i, start;
 
840
    char stub_char;
 
841
 
 
842
    stub_char = (*path == '/') ? '/' : '.';
 
843
 
 
844
    /* Walk along path looking for things to compact. */
 
845
    i = 0;
 
846
    for (;;) {
 
847
        if (!path[i])
 
848
            break;
 
849
 
 
850
        while (path[i] && path[i] != '/')
 
851
            i++;
 
852
 
 
853
        start = i++;
 
854
 
 
855
        /* If we didn't find any slashes, then there is nothing left to do. */
 
856
        if (!path[start])
 
857
            break;
 
858
 
 
859
        /* Handle multiple `/'s in a row. */
 
860
        while (path[i] == '/')
 
861
            i++;
 
862
 
 
863
        if ((start + 1) != i) {
 
864
            strcpy (path + start + 1, path + i);
 
865
            i = start + 1;
 
866
        }
 
867
 
 
868
        /* Handle backquoted `/'. */
 
869
        if (start > 0 && path[start - 1] == '\\')
 
870
            continue;
 
871
 
 
872
        /* Check for trailing `/'. */
 
873
        if (start && !path[i]) {
 
874
        zero_last:
 
875
            path[--i] = '\0';
 
876
            break;
 
877
        }
 
878
 
 
879
        /* Check for `../', `./' or trailing `.' by itself. */
 
880
        if (path[i] == '.') {
 
881
            /* Handle trailing `.' by itself. */
 
882
            if (!path[i + 1])
 
883
                goto zero_last;
 
884
 
 
885
            /* Handle `./'. */
 
886
            if (path[i + 1] == '/') {
 
887
                strcpy (path + i, path + i + 1);
 
888
                i = start;
 
889
                continue;
 
890
            }
 
891
 
 
892
            /* Handle `../' or trailing `..' by itself. 
 
893
               Remove the previous ?/ part with the exception of
 
894
               ../, which we should leave intact. */
 
895
            if (path[i + 1] == '.' && (path[i + 2] == '/' || !path[i + 2])) {
 
896
                while (--start > -1 && path[start] != '/');
 
897
                if (!strncmp (path + start + 1, "../", 3))
 
898
                    continue;
 
899
                strcpy (path + start + 1, path + i + 2);
 
900
                i = start;
 
901
                continue;
 
902
            }
 
903
        }
 
904
    }
 
905
 
 
906
    if (!*path) {
 
907
        *path = stub_char;
 
908
        path[1] = '\0';
 
909
    }
 
910
    return path;
 
911
}
 
912
 
 
913
char *find_dev(dev_t number)
 
914
{
 
915
#ifdef __linux__
 
916
#  define DEVNAME "/dev"
 
917
#else
 
918
#  define DEVNAME "/dev/dsk"
 
919
#endif
 
920
    DIR *dp;
 
921
    char *p;
 
922
    struct dirent *dir;
 
923
    static char name[PATH_MAX+2];
 
924
    struct stat s;
 
925
    char *ret = NULL;
 
926
    int i;
 
927
 
 
928
    if (!number) return NULL;
 
929
    for (i = 0; i < 2; i++) {
 
930
        p = DEVNAME;
 
931
        if (i == 1 && oldroot != -1) {
 
932
            fchdir(oldroot);
 
933
            p++;
 
934
        }
 
935
        if ((dp = opendir(p)) == NULL) continue;
 
936
        strcpy(name + 1,p);
 
937
        p = strchr (name + 1, 0);
 
938
        *p++ = '/';
 
939
        while ((dir = readdir(dp))) {
 
940
            strcpy(p,dir->d_name);
 
941
            if (stat(name + 1,&s) < 0) continue;
 
942
            if (S_ISBLK(s.st_mode) && s.st_rdev == number) {
 
943
                ret = name + 1;
 
944
                if (i == 1 && oldroot != -1) {
 
945
                    name[0] = '/';
 
946
                    ret--;
 
947
                }
 
948
                break;
 
949
            }
 
950
        }
 
951
        if (ret) break;
 
952
    }
 
953
    if (i && oldroot != -1)
 
954
        chdir("/");
 
955
    return ret;
 
956
}
 
957
 
 
958
struct hwdevice *get_device(int majno, int minno)
 
959
{
 
960
    char dev[1024], wholedev[1024];
 
961
    struct hwdevice *hwdev;
 
962
    int unit, part = -1;
 
963
    enum typeenum type = TYPE_UNKNOWN;
 
964
    switch (majno) {
 
965
#ifdef __linux__
 
966
        case 8:
 
967
        case 65:
 
968
        case 66:
 
969
        case 67:
 
970
        case 68:
 
971
        case 69:
 
972
        case 70:
 
973
        case 71:
 
974
                unit = (majno & 7) * 16 + ((minno & 0xf0) >> 4);
 
975
                part = minno & 0xf;
 
976
                if (unit < 26) {
 
977
                        sprintf (dev, "/dev/sd%c%c", unit + 'a', part + '0');
 
978
                        strcpy (wholedev, dev);
 
979
                        wholedev [8] = 0;
 
980
                } else {
 
981
                        sprintf (dev, "/dev/sd%c%c%c", (unit / 26) + 'a' - 1, (unit % 26) + 'a', part + '0');
 
982
                        strcpy (wholedev, dev);
 
983
                        wholedev [9] = 0;
 
984
                }
 
985
                part--;
 
986
                type = TYPE_SCSI;
 
987
                break;
 
988
        case 3: type = TYPE_IDE; unit = 0; goto do_ide;
 
989
        case 22:type = TYPE_IDE; unit = 2; goto do_ide;
 
990
        case 33:
 
991
        case 34:type = TYPE_IDE; unit = 2*(majno - 33) + 4;
 
992
        do_ide: 
 
993
                unit += ((minno & 64) >> 6);
 
994
                part = (minno & 0x3f) - 1;
 
995
                sprintf (dev, "/dev/hd%c%d", unit + 'a', part + 1);
 
996
                strcpy (wholedev, dev);
 
997
                wholedev [8] = 0;
 
998
                break;
 
999
        case 7:         /* Loop device */
 
1000
                unit = minno;
 
1001
                sprintf (dev, "/dev/loop%d", unit);
 
1002
                dev [1023] = 0;
 
1003
                strcpy (wholedev, dev);
 
1004
                break;
 
1005
        case 9:         /* RAID device */
 
1006
                {
 
1007
                        md_array_info_t md_array_info;
 
1008
                        md_disk_info_t md_disk_info;
 
1009
                        int md_fd, i, id = 0;
 
1010
                        struct hwdevice *d, *last;
 
1011
 
 
1012
                        sprintf (dev, "/dev/md%d", minno);
 
1013
                        md_fd = devopen (dev, O_RDONLY);
 
1014
                        if (md_fd < 0)
 
1015
                                silo_fatal("Could not open RAID device");
 
1016
                        if (ioctl (md_fd, GET_ARRAY_INFO, &md_array_info) < 0)
 
1017
                                silo_fatal("Could not get RAID array info");
 
1018
                        if (md_array_info.major_version == 0 && md_array_info.minor_version < 90)
 
1019
                                silo_fatal("Raid versions < 0.90 are not "
 
1020
                                           "supported");
 
1021
                        if (md_array_info.level != 1)
 
1022
                                silo_fatal("Only RAID1 supported");
 
1023
                        hwdev = NULL;
 
1024
                        last = NULL;
 
1025
                        for (i = 0; i < md_array_info.raid_disks; i++) {
 
1026
                                md_disk_info.number = i;
 
1027
                                if (ioctl (md_fd, GET_DISK_INFO, &md_disk_info) < 0)
 
1028
                                        silo_fatal("Could not get RAID disk "
 
1029
                                                   "info for disk %d\n", i);
 
1030
                                if(md_disk_info.majorno != 0 && md_disk_info.minorno != 0) {
 
1031
                                        d = get_device (md_disk_info.majorno, md_disk_info.minorno);
 
1032
                                        if (md_disk_info.state == MD_DISK_FAULTY) {
 
1033
                                                printf ("disk %s marked as faulty, skipping\n", d->dev);
 
1034
                                                continue;
 
1035
                                        }
 
1036
                                        if (hwdev)
 
1037
                                                last->next = d;
 
1038
                                        else
 
1039
                                                hwdev = d;
 
1040
                                        while (d->next != NULL) d = d->next;
 
1041
                                        last = d;
 
1042
                                }
 
1043
                        }
 
1044
                        if (!hwdev)
 
1045
                                silo_fatal("No non-faulty disks found "
 
1046
                                           "in RAID1");
 
1047
                        for (d = hwdev; d; d = d->next)
 
1048
                                d->id = id++;
 
1049
                        raid1 = id;
 
1050
                        close (md_fd);
 
1051
                        return hwdev;
 
1052
                }
 
1053
#endif
 
1054
        default: {
 
1055
                char *p = find_dev (makedev (majno, minno));
 
1056
 
 
1057
                if (!p)
 
1058
                    silo_fatal("Couldn't find out what device is second "
 
1059
                               "stage on");
 
1060
                strcpy (dev, p);
 
1061
                strcpy (wholedev, p);
 
1062
#ifdef __sun__
 
1063
                if (strlen (p) == strlen ("/dev/dsk/c0t0d0s0")) {
 
1064
                    p = strchr (p, 0) - 2;
 
1065
                    if (*p == 's' && p[1] >= '0' && p[1] <= '7') {
 
1066
                        p = strchr (wholedev, 0) - 1;
 
1067
                        *p = '2';
 
1068
                        type = TYPE_SCSI;
 
1069
                        part = p[1] - '0';
 
1070
                    }
 
1071
                }
 
1072
#endif
 
1073
                }
 
1074
                break;
 
1075
    }
 
1076
    hwdev = malloc(sizeof(struct hwdevice) + strlen(dev) + strlen(wholedev) + 4);
 
1077
    if (!hwdev)
 
1078
        silo_fatal("Not enough memory");
 
1079
    memset(hwdev, 0, sizeof(*hwdev));
 
1080
    hwdev->dev = (char *)(hwdev + 1);
 
1081
    strcpy (hwdev->dev, dev);
 
1082
    hwdev->wholedev = strchr(hwdev->dev, 0) + 2;
 
1083
    strcpy (hwdev->wholedev, wholedev);
 
1084
    hwdev->part = part;
 
1085
    hwdev->partat0 = -1;
 
1086
    hwdev->type = type;
 
1087
    return hwdev;
 
1088
}
 
1089
 
 
1090
int main(int argc,char **argv)
 
1091
{
 
1092
    char *name = NULL, *config_file, *install = NULL, *secondary = NULL, *backup, *p;
 
1093
    struct utsname uts;
 
1094
    int version = 0;
 
1095
    struct stat st1, st2, st3;
 
1096
    int force_backup = 0;
 
1097
    int config_file_partno = 1;
 
1098
    int force = 0, f;
 
1099
    struct hwdevice *hwdev;
 
1100
    
 
1101
    int use_prom = 0;
 
1102
    int print_prom_version = 0;
 
1103
 
 
1104
#ifdef __sun__
 
1105
    if (prom_init () >= 0)
 
1106
        use_prom = 1;
 
1107
#endif
 
1108
    if (uname (&uts) >= 0 && !strcmp (uts.machine, "sparc64"))
 
1109
        ultra = 1;
 
1110
    config_file = DFL_CONFIG;
 
1111
    backup = DFL_BACKUP;
 
1112
    new_root = NULL;
 
1113
    name = *argv++;
 
1114
    argc--;
 
1115
    while (argc && **argv == '-') {
 
1116
        argc--;
 
1117
        if (argv[0][2] && argv[0][1] != 'p') usage(name);
 
1118
        switch ((*argv++)[1]) {
 
1119
            case 'b':
 
1120
                if (!argc) usage(name);
 
1121
                secondary = *argv++;
 
1122
                argc--;
 
1123
                break;
 
1124
            case 'i':
 
1125
                if (!argc) usage(name);
 
1126
                install = *argv++;
 
1127
                argc--;
 
1128
                break;
 
1129
            case 'F':
 
1130
                floppy_image = 1;
 
1131
                break;
 
1132
            case 'p':
 
1133
                if ((argv[-1])[2] == '0')
 
1134
                    promver = 0;
 
1135
                else if ((argv[-1])[2] == '2')
 
1136
                    promver = 2;
 
1137
                else if (argv[-1][2])
 
1138
                    usage(name);
 
1139
                else if (argc && **argv == '0') {
 
1140
                    promver = 0;
 
1141
                    argv++;
 
1142
                    argc--;
 
1143
                } else if (argc && **argv == '2') {
 
1144
                    promver = 2;
 
1145
                    argv++;
 
1146
                    argc--;
 
1147
                } else usage(name);
 
1148
                break;
 
1149
            case 'f':
 
1150
                force = 1;
 
1151
                break;
 
1152
            case 'C':
 
1153
                if (!argc) usage(name);
 
1154
                config_file = *argv++;
 
1155
                argc--;
 
1156
                break;
 
1157
            case 'S':
 
1158
                if (!argc) usage(name);
 
1159
                backup = *argv++;
 
1160
                force_backup = 1;
 
1161
                argc--;
 
1162
                break;
 
1163
            case 's':
 
1164
                if (!argc) usage(name);
 
1165
                backup = *argv++;
 
1166
                argc--;
 
1167
                break;
 
1168
            case 'r':
 
1169
                if (!argc) usage(name);
 
1170
                new_root = *argv++;
 
1171
                argc--;
 
1172
                break;
 
1173
            case 'V':
 
1174
                version = 1;
 
1175
                break;
 
1176
            case 't':
 
1177
                masterboot = 0;
 
1178
                break;
 
1179
            case 'v':
 
1180
                print_prom_version = 1;
 
1181
                break;
 
1182
            case 'u':
 
1183
                ultra = 1;
 
1184
                break;
 
1185
            case 'U':
 
1186
                ultra = 0;
 
1187
                break;
 
1188
            case 'J':
 
1189
                if (!argc) usage(name);
 
1190
                flash_image = *argv++;
 
1191
                argc--;
 
1192
                break;
 
1193
            case 'a':
 
1194
                allow_confchk_fail = 1;
 
1195
                break;
 
1196
            default:
 
1197
                usage(name);
 
1198
        }
 
1199
    }
 
1200
    if (promver == -1 && !ultra)
 
1201
        promver = get_prom_ver(use_prom);
 
1202
    else if (!ultra)
 
1203
        prombug = 1;
 
1204
    else
 
1205
        prombug = 0;
 
1206
    if (print_prom_version) {
 
1207
        if (ultra)
 
1208
                printf("IEEE 1275\n");
 
1209
        else
 
1210
                printf ("%d\n", promver);
 
1211
        return 0;
 
1212
    }
 
1213
    if (!new_root) new_root = getenv("ROOT");
 
1214
    if (version) {
 
1215
        fprintf(stderr, "SILO version " VERSION "\n");
 
1216
        return 0;
 
1217
    }
 
1218
    if (argc) usage(name);
 
1219
    if (floppy_image && flash_image) usage(name);
 
1220
 
 
1221
    if (flash_image) {
 
1222
        char *p, *q;
 
1223
        if (*flash_image == '/') {
 
1224
            p = malloc(strlen(flash_image) + 2);
 
1225
            strcpy(p, flash_image);
 
1226
        } else {
 
1227
#ifdef __linux__
 
1228
            q = getcwd(NULL, 0);
 
1229
            p = malloc(strlen(flash_image) + 3 + strlen(q));
 
1230
            strcpy(p, q);
 
1231
            free(q);
 
1232
#else
 
1233
            p = malloc(PATH_MAX + 3 + strlen(flash_image));
 
1234
            getcwd(p, PATH_MAX);
 
1235
#endif
 
1236
            strcat(p, "/");
 
1237
            strcat(p, flash_image);
 
1238
        }
 
1239
        flash_image = p;
 
1240
    }
 
1241
 
 
1242
    if (new_root && strcmp("/", new_root)) {
 
1243
       if (stat (new_root, &st1) < 0 || !S_ISDIR(st1.st_mode)) {
 
1244
           silo_fatal("New root %s is not a directory", new_root);
 
1245
       }
 
1246
       oldroot = open("/", O_RDONLY);
 
1247
       chroot(new_root);
 
1248
       chdir("/");
 
1249
    }
 
1250
 
 
1251
    /* This _must_ be done after chrooting */
 
1252
    if (!confcheck(config_file) && !allow_confchk_fail)
 
1253
        return 1;
 
1254
 
 
1255
    /* Check for some values in the config that override defaults */
 
1256
    if (cfg_get_flag(NULL, "partition-boot"))
 
1257
        masterboot = 0;
 
1258
 
 
1259
    if (!secondary) {
 
1260
        if (cfg_get_strg(NULL, "secondary"))
 
1261
            secondary = cfg_get_strg(NULL, "secondary");
 
1262
        else
 
1263
            secondary = DFL_SECONDARY;
 
1264
    }
 
1265
 
 
1266
    secondary = strdup (secondary);
 
1267
    if (stat (secondary, &st1) < 0)
 
1268
        silo_fatal("Cannot open second stage loader %s", secondary);
 
1269
    hwdevs = get_device (mmajor(st1.st_dev), mminor(st1.st_dev));
 
1270
    if (raid1 > 32)
 
1271
        silo_fatal("SILO supports at most 32 disks in the RAID1 array");
 
1272
    if (raid1 && masterboot) {
 
1273
        struct hwdevice *d, *d1;
 
1274
        /* Check if we have to remove some RAID1 mirrors, because
 
1275
           we can support only one RAID1 mirror per physical device
 
1276
           if masterboot.  */
 
1277
        for (d = hwdevs; d; d = d->next)
 
1278
            for (d1 = d; d1->next; d1 = d1->next)
 
1279
                if (!strcmp (d->wholedev, d1->next->wholedev)) {
 
1280
                    d1->next = d1->next->next;
 
1281
                    raid1--;
 
1282
                }
 
1283
    }
 
1284
    if (flash_image) {
 
1285
        /*
 
1286
         * The filesystem starts at offset 1024 into the flash. This
 
1287
         * makes it impossible to patch the first stage through /dev/loopN.
 
1288
         * We use argument to -J as a way to access the whole flash image.
 
1289
         *
 
1290
         * XXX There is no good way to ensure that argument to -J
 
1291
         * is what we have mounted off a loopback or a ramdisk.
 
1292
         * So we do not bother trying.
 
1293
         */
 
1294
        if (raid1)
 
1295
            silo_fatal("-J cannot be used with RAID1");
 
1296
        hwdevs->wholedev = flash_image;
 
1297
    }
 
1298
    p = backup;
 
1299
    backup = malloc (strlen(backup) + 20);
 
1300
    config_file = strdup (config_file);
 
1301
    strcpy (backup, p);
 
1302
    if (!backup || !config_file)
 
1303
        silo_fatal("Not enough memory");
 
1304
    if (stat (config_file, &st2) >= 0) {
 
1305
        if (raid1 && st1.st_dev != st2.st_dev)
 
1306
            silo_fatal("Config file %s has to be on the same RAID1 device "
 
1307
                       "as second stage bootblock", config_file);
 
1308
        else if (hwdevs->type == TYPE_UNKNOWN && st1.st_dev != st2.st_dev)
 
1309
            silo_fatal("Config file %s has to be on the %s device",
 
1310
                       config_file, hwdevs->dev);
 
1311
#ifdef __linux__
 
1312
        else if ((hwdevs->type == TYPE_SCSI && (mmajor(st2.st_dev) != mmajor(st1.st_dev) || (mminor(st2.st_dev) & (~0xf)) != (mminor(st1.st_dev) & (~0xf)))) ||
 
1313
            (hwdevs->type == TYPE_IDE && (mmajor(st2.st_dev) != mmajor(st1.st_dev) || (mminor(st2.st_dev) & (~0x3f)) != (mminor(st1.st_dev) & (~0x3f)))))
 
1314
#elif defined(__sun__)
 
1315
        else if (hwdevs->type == TYPE_SCSI && (st2.st_dev & (~0x7)) != (st1.st_dev & (~0x7)))
 
1316
#else
 
1317
#  error "Unknown system"
 
1318
#endif
 
1319
            silo_fatal("Config file %s has to be on the %s device "
 
1320
                       "(on any partition there)", config_file,
 
1321
                       hwdevs->wholedev);
 
1322
        else {
 
1323
            char *p, *q, *r, c;
 
1324
            char readlinkbuf[2048];
 
1325
            int len;
 
1326
            char buffer[2048], buffer2[2048];
 
1327
 
 
1328
            strcpy (buffer, config_file);
 
1329
            for (p = buffer;;) {
 
1330
                q = strchr (p, '/');
 
1331
                if (q) {
 
1332
                    c = *q;
 
1333
                    *q = 0;
 
1334
                } else c = 0;
 
1335
                if (lstat (*buffer ? buffer : "/", &st3) < 0)
 
1336
                    silo_fatal("Couldn't stat %s\n", config_file);
 
1337
                if (st3.st_dev == st2.st_dev) {
 
1338
                    *q = c;
 
1339
                    config_file = q;
 
1340
                    break;
 
1341
                }
 
1342
                if (S_ISLNK(st3.st_mode)) {
 
1343
                    len = readlink (buffer, readlinkbuf, 2048);
 
1344
                    if (len < 0)
 
1345
                        silo_fatal("Couldn't readlink %s\n", config_file);
 
1346
                    readlinkbuf[len] = 0;
 
1347
                    if (*readlinkbuf == '/') {
 
1348
                        if (c) {
 
1349
                            r = readlinkbuf+len;
 
1350
                            if (readlinkbuf[len - 1] != '/')
 
1351
                                *r++ = '/';
 
1352
                            strcpy (r, q + 1);
 
1353
                        }
 
1354
                        strcpy (buffer, readlinkbuf);
 
1355
                        p = buffer + 1;
 
1356
                        continue;
 
1357
                    } else {
 
1358
                        r = strrchr (buffer, '/');
 
1359
                        memcpy (buffer2, buffer, r - buffer + 1);
 
1360
                        strcpy (buffer2 + (r - buffer + 1), readlinkbuf);
 
1361
                        if (c) {
 
1362
                            strcat (buffer2, "/");
 
1363
                            strcat (buffer2, q + 1);
 
1364
                        }
 
1365
                        strcpy (buffer, buffer2);
 
1366
                        p = buffer + 1;
 
1367
                        continue;
 
1368
                    }
 
1369
                } else {
 
1370
                    *q = c;
 
1371
                    p = q + 1;
 
1372
                    if (!c)
 
1373
                        silo_fatal("Internal error\n");
 
1374
                }
 
1375
            }                          
 
1376
        }
 
1377
        if (raid1)
 
1378
            config_file_partno = -1;
 
1379
        else if (hwdevs->type == TYPE_SCSI)
 
1380
#ifdef __linux__        
 
1381
            config_file_partno = (mminor(st2.st_dev) & 0x0f);
 
1382
#elif defined(__sun__)
 
1383
            config_file_partno = (st2.st_dev & 7) + 1;
 
1384
#else
 
1385
#  error "Unknown system"
 
1386
#endif
 
1387
#ifdef __linux__        
 
1388
        else if (hwdevs->type == TYPE_IDE)
 
1389
            config_file_partno = (mminor(st2.st_dev) & 0x3f);
 
1390
#endif
 
1391
        else
 
1392
            config_file_partno = 1;
 
1393
    }
 
1394
    for (hwdev = hwdevs; hwdev; hwdev = hwdev->next)
 
1395
        read_sb (hwdev);
 
1396
    for (hwdev = hwdevs, f = 0; hwdev; hwdev = hwdev->next) {
 
1397
        int fb = force_backup;
 
1398
 
 
1399
        p = NULL;
 
1400
        if (raid1) {
 
1401
            p = strchr (backup, 0);
 
1402
            sprintf (p, "-raid1-%d", hwdev->id);
 
1403
        }
 
1404
        if (!force_backup) {
 
1405
            if (stat (backup, &st2) < 0)
 
1406
                fb = 2;
 
1407
        }
 
1408
        f |= examine_bootblock (masterboot ? hwdev->wholedev : hwdev->dev, backup, fb);
 
1409
        if (p)
 
1410
            *p = 0;
 
1411
    }
 
1412
    if (f || install || force) {
 
1413
        if (!install)
 
1414
            install = strdup (ultra ? DFL_PRIMARY_U : DFL_PRIMARY);
 
1415
        else if (*install == '/')
 
1416
            install = strdup (install);
 
1417
        for (hwdev = hwdevs; hwdev; hwdev = hwdev->next)
 
1418
            install_first_stage (masterboot ? hwdev->wholedev : hwdev->dev, install);
 
1419
    }
 
1420
    make_room_for_raid1(hwdevs, secondary);
 
1421
    for (hwdev = hwdevs; hwdev; hwdev = hwdev->next)
 
1422
        get_partition_blocks (hwdev, secondary);
 
1423
    write_block_tables (hwdevs, secondary, config_file, config_file_partno);
 
1424
    sync();
 
1425
    exit(0);
 
1426
}
 
1427
 
 
1428
#ifdef __sun__
 
1429
 
 
1430
static errcode_t std_open (const char *name, int flags, io_channel * channel);
 
1431
static errcode_t std_close (io_channel channel);
 
1432
static errcode_t std_set_blksize (io_channel channel, int blksize);
 
1433
static errcode_t std_read_blk (io_channel channel, unsigned long block, int count, void *data);
 
1434
static errcode_t std_write_blk (io_channel channel, unsigned long block, int count, const void *data);
 
1435
static errcode_t std_flush (io_channel channel);
 
1436
 
 
1437
static struct struct_io_manager struct_std_manager =
 
1438
{
 
1439
    EXT2_ET_MAGIC_IO_MANAGER,
 
1440
    "linux I/O Manager",
 
1441
    std_open,
 
1442
    std_close,
 
1443
    std_set_blksize,
 
1444
    std_read_blk,
 
1445
    std_write_blk,
 
1446
    std_flush
 
1447
};
 
1448
 
 
1449
static ufs_filsys fs = NULL;
 
1450
static io_manager std_io_manager = &struct_std_manager;
 
1451
static int std_fd = 0;
 
1452
 
 
1453
static unsigned int cbs = 1024;         /* Block Size */
 
1454
 
 
1455
static errcode_t std_open (const char *name, int flags, io_channel * channel)
 
1456
{
 
1457
    int partno;
 
1458
    io_channel io;
 
1459
 
 
1460
    if (!name)
 
1461
        return EXT2_ET_BAD_DEVICE_NAME;
 
1462
    io = (io_channel) malloc (sizeof (struct struct_io_channel));
 
1463
    if (!io)
 
1464
        return EXT2_ET_BAD_DEVICE_NAME;
 
1465
    std_fd = devopen (name, O_RDONLY);
 
1466
    if (std_fd < 0)
 
1467
        silo_fatal("Cannot open %s", name);
 
1468
    memset (io, 0, sizeof (struct struct_io_channel));
 
1469
    io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
 
1470
    io->manager = std_io_manager;
 
1471
    io->name = (char *) malloc (strlen (name) + 1);
 
1472
    strcpy (io->name, name);
 
1473
    io->block_size = cbs;
 
1474
    io->read_error = 0;
 
1475
    io->write_error = 0;
 
1476
 
 
1477
    *channel = io;
 
1478
    return 0;
 
1479
}
 
1480
 
 
1481
static errcode_t std_close (io_channel channel)
 
1482
{
 
1483
    close (std_fd);
 
1484
}
 
1485
 
 
1486
static errcode_t std_set_blksize (io_channel channel, int blksize)
 
1487
{
 
1488
    channel->block_size = cbs = blksize;
 
1489
}
 
1490
 
 
1491
static errcode_t std_read_blk (io_channel channel, unsigned long block, int count, void *data)
 
1492
{
 
1493
    int size;
 
1494
 
 
1495
    size = (count < 0) ? -count : count * cbs;
 
1496
    if (lseek (std_fd, block * cbs, SEEK_SET) != block * cbs)
 
1497
        silo_fatal("Cannot seek");
 
1498
    if (read (std_fd, data, size) != size)
 
1499
        silo_fatal("Read error on block %d", block);
 
1500
    return 0;
 
1501
}
 
1502
 
 
1503
static errcode_t std_write_blk (io_channel channel, unsigned long block, int count, const void *data)
 
1504
{
 
1505
}
 
1506
 
 
1507
static errcode_t std_flush (io_channel channel)
 
1508
{
 
1509
}
 
1510
 
 
1511
static int ufs_block_idx = 0;
 
1512
static int ufs_blocks_dump (ufs_filsys fs, blk_t *block, int i, void *private)
 
1513
{
 
1514
    int j;
 
1515
    struct hwdevice *hwdev = (struct hwdevice *)private;
 
1516
    for (j = 0; j < hwdev->nsect; j++)
 
1517
        blocks [ufs_block_idx++] = *block * hwdev->nsect + hwdev->doff + j;
 
1518
    return 0;
 
1519
}
 
1520
 
 
1521
static int ufs_blocks (struct hwdevice *hwdev, ino_t inode)
 
1522
{
 
1523
    if (ufs_open (hwdev->dev, std_io_manager, &fs))
 
1524
        silo_fatal("Cannot open ufs filesystem containing second stage");
 
1525
    hwdev->nsect = cbs / 512;
 
1526
    if (ufs_block_iterate (fs, inode, ufs_blocks_dump, hwdev))
 
1527
        silo_fatal("Block iterating error on second stage");
 
1528
    blocks [ufs_block_idx] = 0;
 
1529
    return 0;
 
1530
}
 
1531
 
 
1532
#endif