~ubuntu-branches/ubuntu/hoary/s390-tools/hoary

« back to all changes in this revision

Viewing changes to zipl/src/install.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2004-06-27 18:45:15 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040627184515-ch5tgtkar5lp3bgz
Tags: 1.3.1-2
* zipl:
  - Add support for optional ipl images.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * s390-tools/zipl/src/install.c
 
3
 *   Functions handling the installation of the boot loader code onto disk.
 
4
 *
 
5
 * Copyright (C) 2001-2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
 
6
 *
 
7
 * Author(s): Carsten Otte <cotte@de.ibm.com>
 
8
 *            Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>
 
9
 */
 
10
 
 
11
#include "install.h"
 
12
 
 
13
#include <sys/types.h>
 
14
#include <sys/stat.h>
 
15
#include <sys/ioctl.h>
 
16
#include <fcntl.h>
 
17
#include <stdio.h>
 
18
#include <string.h>
 
19
#include <errno.h>
 
20
#include <unistd.h>
 
21
#include <stdlib.h>
 
22
#include <stdarg.h>
 
23
#include <sys/mtio.h>
 
24
#include <syslog.h>
 
25
 
 
26
#include "boot.h"
 
27
#include "bootmap.h"
 
28
#include "disk.h"
 
29
#include "error.h"
 
30
#include "misc.h"
 
31
 
 
32
 
 
33
/* Types of SCSI disk layouts */
 
34
enum scsi_layout {
 
35
        scsi_layout_pcbios,
 
36
        scsi_layout_sun,
 
37
        scsi_layout_sgi,
 
38
        scsi_layout_unknown
 
39
};
 
40
 
 
41
 
 
42
/* Determine SCSI disk layout from the specified BOOTBLOCK. */
 
43
static enum scsi_layout
 
44
get_scsi_layout(unsigned char* bootblock)
 
45
{
 
46
        if ((bootblock[510] == 0x55) && (bootblock[511] == 0xaa))
 
47
                return scsi_layout_pcbios;
 
48
        else if ((bootblock[508] == 0xda) && (bootblock[509] == 0xbe))
 
49
                return scsi_layout_sun;
 
50
        else if ((bootblock[0] == 0x0b) && (bootblock[1] == 0xe5) &&
 
51
                 (bootblock[2] == 0xa9) && (bootblock[3] == 0x41))
 
52
                return scsi_layout_sgi;
 
53
        return scsi_layout_unknown;
 
54
}
 
55
 
 
56
 
 
57
#define DISK_LAYOUT_ID 0x00000001
 
58
 
 
59
/* Create an IPL master boot record data structure for SCSI MBRs in memory
 
60
 * at location BUFFER. TABLE contains a pointer to the program table. INFO
 
61
 * provides information about the disk. */
 
62
static int
 
63
update_scsi_mbr(void* bootblock, disk_blockptr_t* table,
 
64
                struct disk_info* info)
 
65
{
 
66
        struct scsi_mbr {
 
67
                uint8_t         magic[4];
 
68
                uint32_t        version_id;
 
69
                uint8_t         reserved[8];
 
70
                uint8_t         program_table_pointer[16];
 
71
        }* mbr;
 
72
        void* buffer;
 
73
 
 
74
        switch (get_scsi_layout(bootblock)) {
 
75
        case scsi_layout_pcbios:
 
76
                if (verbose)
 
77
                        printf("Detected SCSI PCBIOS disk layout.\n");
 
78
                buffer = bootblock;
 
79
                break;
 
80
        case scsi_layout_sun:
 
81
        case scsi_layout_sgi:
 
82
        default:
 
83
                error_reason("Unsupported SCSI disk layout");
 
84
                return -1;
 
85
        }
 
86
 
 
87
        mbr = (struct scsi_mbr *) buffer;
 
88
        memset(buffer, 0, sizeof(struct scsi_mbr));
 
89
        memcpy(&mbr->magic, ZIPL_MAGIC, ZIPL_MAGIC_SIZE);
 
90
        mbr->version_id = DISK_LAYOUT_ID;
 
91
        bootmap_store_blockptr(&mbr->program_table_pointer, table, info);
 
92
        return 0;
 
93
}
 
94
 
 
95
 
 
96
/* Install bootloader for initial program load from a SCSI type disk. FD
 
97
 * specifies the file descriptor of the device file. PROGRAM_TABLE points
 
98
 * to the disk block containing the program table. INFO provides
 
99
 * information about the disk type. Return 0 on success, non-zero otherwise. */
 
100
static int
 
101
install_scsi(int fd, disk_blockptr_t* program_table, struct disk_info* info)
 
102
{
 
103
        unsigned char* bootblock;
 
104
        int rc;
 
105
 
 
106
        bootblock = (unsigned char*) misc_malloc(info->phy_block_size);
 
107
        if (bootblock == NULL)
 
108
                return -1;
 
109
        /* Read bootblock */
 
110
        if (lseek(fd, 0, SEEK_SET) != 0) {
 
111
                error_reason(strerror(errno));
 
112
                error_text("Could not seek on device");
 
113
                free(bootblock);
 
114
                return -1;
 
115
        }
 
116
        rc = misc_read(fd, bootblock, info->phy_block_size);
 
117
        if (rc) {
 
118
                error_text("Could not read master boot record");
 
119
                free(bootblock);
 
120
                return rc;
 
121
        }
 
122
        /* Put zIPL data into MBR */
 
123
        rc = update_scsi_mbr(bootblock, program_table, info);
 
124
        if (rc) {
 
125
                free(bootblock);
 
126
                return -1;
 
127
        }
 
128
        /* Write MBR back to disk */
 
129
        if (verbose)
 
130
                printf("Writing SCSI master boot record.\n");
 
131
        if (lseek(fd, 0, SEEK_SET) != 0) {
 
132
                error_reason(strerror(errno));
 
133
                error_text("Could not seek on device");
 
134
                free(bootblock);
 
135
                return -1;
 
136
        }
 
137
        rc = misc_write(fd, bootblock, info->phy_block_size);
 
138
        if (rc)
 
139
                error_text("Could not write master boot record");
 
140
        free(bootblock);
 
141
        return rc;
 
142
}
 
143
 
 
144
 
 
145
/* Install bootloader for initial program load from an FBA type disk. */
 
146
static int
 
147
install_fba(int fd, disk_blockptr_t* program_table,
 
148
            disk_blockptr_t* stage2_list, blocknum_t stage2_count,
 
149
            struct disk_info* info)
 
150
{
 
151
        struct boot_fba_stage0 stage0;
 
152
        int rc;
 
153
 
 
154
        /* Initialize stage 0 data */
 
155
        rc = boot_init_fba_stage0(&stage0, program_table, stage2_list,
 
156
                                  stage2_count, info);
 
157
        if (rc == 0) {
 
158
                /* Install stage 0 */
 
159
                rc = misc_write(fd, &stage0, sizeof(struct boot_fba_stage0));
 
160
        }
 
161
        if (rc)
 
162
                error_text("Could not write boot loader");
 
163
        return rc;
 
164
}
 
165
 
 
166
 
 
167
/* Install bootloader for initial program load from an ECKD type disk with
 
168
 * Linux/390 classic disk layout. */
 
169
static int
 
170
install_eckd_classic(int fd, disk_blockptr_t* program_table,
 
171
                     disk_blockptr_t* stage2_list, blocknum_t stage2_count,
 
172
                     struct disk_info* info, struct job_data* job)
 
173
{
 
174
        struct boot_eckd_stage0 stage0;
 
175
        struct boot_eckd_classic_stage1 stage1;
 
176
        int rc;
 
177
 
 
178
        /* Prepare stage 0 */
 
179
        boot_init_eckd_classic_stage0(&stage0);
 
180
        /* Install stage 0 */
 
181
        rc = misc_write(fd, &stage0, sizeof(struct boot_eckd_stage0));
 
182
        if (rc) {
 
183
                error_text("Could not write boot loader");
 
184
                return rc;
 
185
        }
 
186
        /* Prepare stage 1 */
 
187
        rc = boot_init_eckd_classic_stage1(&stage1, stage2_list, stage2_count,
 
188
                                           info);
 
189
        if (rc)
 
190
                return rc;
 
191
        /* Store program table pointer in stage 1 loader */
 
192
        bootmap_store_blockptr(&stage1.param1, program_table, info);
 
193
        /* Install stage 1 */
 
194
        if (lseek(fd, info->phy_block_size, SEEK_SET) !=
 
195
            info->phy_block_size) {
 
196
                error_reason(strerror(errno));
 
197
                error_text("Could not seek on device");
 
198
                return -1;
 
199
        }
 
200
        rc = misc_write(fd, &stage1, sizeof(struct boot_eckd_classic_stage1));
 
201
        if (rc) {
 
202
                error_text("Could not write boot loader");
 
203
                return rc;
 
204
        }
 
205
        return rc;
 
206
}
 
207
 
 
208
 
 
209
 
 
210
/* Install bootloader for initial program load from an ECKD type disk with
 
211
 * OS/390 compatible disk layout. */
 
212
static int
 
213
install_eckd_compatible(int fd, disk_blockptr_t* program_table,
 
214
                        struct disk_info* info, struct job_data* job)
 
215
{
 
216
        struct boot_eckd_stage0 stage0;
 
217
        struct boot_eckd_compatible_stage1 stage1;
 
218
        void* buffer;
 
219
        size_t size;
 
220
        int rc;
 
221
 
 
222
        /* Prepare stage 0 */
 
223
        boot_init_eckd_compatible_stage0(&stage0);
 
224
        /* Install stage 0 */
 
225
        if (lseek(fd, 4, SEEK_SET) != 4) {
 
226
                error_reason(strerror(errno));
 
227
                error_text("Could not seek on device");
 
228
                return -1;
 
229
        }
 
230
        rc = misc_write(fd, &stage0, sizeof(struct boot_eckd_stage0));
 
231
        if (rc) {
 
232
                error_text("Could not write boot loader");
 
233
                return -1;
 
234
        }
 
235
        /* Prepare stage 1 */
 
236
        rc = boot_init_eckd_compatible_stage1(&stage1, info);
 
237
        if (rc)
 
238
                return rc;
 
239
        /* Store program table pointer in stage 1 loader */
 
240
        bootmap_store_blockptr(&stage1.param1, program_table, info);
 
241
        /* Install stage 1 */
 
242
        if (lseek(fd, 4 + info->phy_block_size, SEEK_SET) !=
 
243
            4 + info->phy_block_size) {
 
244
                error_reason(strerror(errno));
 
245
                error_text("Could not seek on device");
 
246
                return -1;
 
247
        }
 
248
        rc = misc_write(fd, &stage1,
 
249
                        sizeof(struct boot_eckd_compatible_stage1));
 
250
        if (rc) {
 
251
                error_text("Could not write boot loader");
 
252
                return -1;
 
253
        }
 
254
        /* Install stage 2 */
 
255
        if (lseek(fd, 3 * info->phy_block_size, SEEK_SET) !=
 
256
            3 * info->phy_block_size) {
 
257
                error_reason(strerror(errno));
 
258
                error_text("Could not seek on device");
 
259
                return -1;
 
260
        }
 
261
        rc = boot_get_eckd_stage2(&buffer, &size, job);
 
262
        if (rc)
 
263
                return -1;
 
264
        rc = misc_write(fd, buffer, size);
 
265
        if (rc)
 
266
                error_text("Could not write boot loader");
 
267
        free(buffer);
 
268
        return rc;
 
269
}
 
270
 
 
271
 
 
272
int
 
273
install_bootloader(const char* device, disk_blockptr_t *program_table,
 
274
                   disk_blockptr_t* stage2_list, blocknum_t stage2_count,
 
275
                   struct disk_info* info, struct job_data* job)
 
276
{
 
277
        int fd;
 
278
        int rc;
 
279
 
 
280
        /* Inform user about what we're up to */
 
281
        printf("Preparing boot device: ");
 
282
        if (info->name) {
 
283
                printf("%s", info->name);
 
284
                if (info->devno >= 0)
 
285
                        printf(" (%04x)", info->devno);
 
286
                printf(".\n");
 
287
        } else if (info->devno >= 0) {
 
288
                printf("%04x.\n", info->devno);
 
289
        } else
 
290
                disk_print_devt(info->device);
 
291
        /* Open device file */
 
292
        fd = open(device, O_RDWR);
 
293
        if (fd == -1) {
 
294
                error_reason(strerror(errno));
 
295
                error_text("Could not open temporary device file '%s'",
 
296
                           device);
 
297
                return -1;
 
298
        }
 
299
        /* Call disk specific install functions */
 
300
        rc = -1;
 
301
        switch (info->type) {
 
302
        case disk_type_scsi:
 
303
                rc = install_scsi(fd, program_table, info);
 
304
                break;
 
305
        case disk_type_fba:
 
306
                rc = install_fba(fd, program_table, stage2_list, stage2_count,
 
307
                                 info);
 
308
                break;
 
309
        case disk_type_eckd_classic:
 
310
                rc = install_eckd_classic(fd, program_table, stage2_list,
 
311
                                          stage2_count, info, job);
 
312
                break;
 
313
        case disk_type_eckd_compatible:
 
314
                rc = install_eckd_compatible(fd, program_table, info, job);
 
315
                break;
 
316
        case disk_type_diag:
 
317
        case disk_type_unknown:
 
318
                /* Should not happen */
 
319
                break;
 
320
        }
 
321
        close(fd);
 
322
        if (rc == 0) {
 
323
                if (info->devno >= 0)
 
324
                        syslog(LOG_INFO, "Boot loader written to %s (%04x) - "
 
325
                               "%02x:%02x",
 
326
                               (info->name ? info->name : "-"), info->devno,
 
327
                               major(info->device), minor(info->device));
 
328
                else
 
329
                        syslog(LOG_INFO, "Boot loader written to %s - "
 
330
                               "%02x:%02x",
 
331
                               (info->name ? info->name : "-"),
 
332
                               major(info->device), minor(info->device));
 
333
        }
 
334
        return rc;
 
335
}
 
336
 
 
337
 
 
338
/* Rewind the tape device identified by FD. Return 0 on success, non-zero
 
339
 * otherwise. */
 
340
static int
 
341
rewind_tape(int fd)
 
342
{
 
343
        struct mtop op;
 
344
 
 
345
        /* Magnetic tape rewind operation */
 
346
        op.mt_count = 1;
 
347
        op.mt_op = MTREW;
 
348
        if (ioctl(fd, MTIOCTOP, &op) == -1)
 
349
                return -1;
 
350
        else
 
351
                return 0;
 
352
}
 
353
 
 
354
 
 
355
static int
 
356
ask_for_confirmation(const char* fmt, ...)
 
357
{
 
358
        va_list args;
 
359
        char answer;
 
360
 
 
361
        /* Always assume positive answer in non-interactive mode */
 
362
        if (!interactive)
 
363
                return 0;
 
364
        /* Print question */
 
365
        va_start(args, fmt);
 
366
        vprintf(fmt, args);
 
367
        va_end(args);
 
368
        /* Process user reply */
 
369
        scanf("%c", &answer);
 
370
        if ((answer == 'y') || (answer == 'Y'))
 
371
                return 0;
 
372
        error_text("Operation canceled by user");
 
373
        return -1;
 
374
}
 
375
 
 
376
 
 
377
/* Write data from file FILENAME to file descriptor FD. Data will be written
 
378
 * in blocks of BLOCKSIZE bytes. Return 0 on success, non-zero otherwise. */
 
379
static int
 
380
write_tapefile(int fd, const char* filename, size_t blocksize)
 
381
{
 
382
        struct stat stats;
 
383
        ssize_t written;
 
384
        size_t offset;
 
385
        size_t chunk;
 
386
        void* buffer;
 
387
        int read_fd;
 
388
 
 
389
        if (stat(filename, &stats)) {
 
390
                error_reason(strerror(errno));
 
391
                return -1;
 
392
        }
 
393
        if (!S_ISREG(stats.st_mode)) {
 
394
                error_reason("Not a regular file");
 
395
                return -1;
 
396
        }
 
397
        buffer = misc_malloc(blocksize);
 
398
        if (buffer == NULL)
 
399
                return -1;
 
400
        read_fd = open(filename, O_RDONLY);
 
401
        if (fd == -1) {
 
402
                error_reason(strerror(errno));
 
403
                free(buffer);
 
404
                return -1;
 
405
        }
 
406
        for (offset = 0; offset < stats.st_size; offset += chunk) {
 
407
                chunk = stats.st_size - offset;
 
408
                if (chunk > blocksize)
 
409
                        chunk = blocksize;
 
410
                else
 
411
                        memset(buffer, 0, blocksize);
 
412
                if (misc_read(read_fd, buffer, chunk)) {
 
413
                        close(read_fd);
 
414
                        free(buffer);
 
415
                        return -1;
 
416
                }
 
417
                written = write(fd, buffer, chunk);
 
418
                if (written != chunk) {
 
419
                        if (written == -1)
 
420
                                error_reason(strerror(errno));
 
421
                        else
 
422
                                error_reason("Write error");
 
423
                        close(read_fd);
 
424
                        free(buffer);
 
425
                        return -1;
 
426
                }
 
427
        }
 
428
        close(read_fd);
 
429
        free(buffer);
 
430
        return 0;
 
431
}
 
432
 
 
433
 
 
434
/* Write SIZE bytes of data from memory location DATA to file descriptor FD.
 
435
 * Data will be written in blocks of BLOCKSIZE bytes. Return 0 on success,
 
436
 * non-zero otherwise. */
 
437
static int
 
438
write_tapebuffer(int fd, const char* data, size_t size, size_t blocksize)
 
439
{
 
440
        ssize_t written;
 
441
        size_t offset;
 
442
        size_t chunk;
 
443
        void* buffer;
 
444
 
 
445
        buffer = misc_malloc(blocksize);
 
446
        if (buffer == NULL)
 
447
                return -1;
 
448
        for (offset = 0; offset < size; offset += chunk) {
 
449
                chunk = size - offset;
 
450
                if (chunk > blocksize)
 
451
                        chunk = blocksize;
 
452
                else
 
453
                        memset(buffer, 0, blocksize);
 
454
                memcpy(buffer, VOID_ADD(data, offset), chunk);
 
455
                written = write(fd, buffer, chunk);
 
456
                if (written != chunk) {
 
457
                        if (written == -1)
 
458
                                error_reason(strerror(errno));
 
459
                        else
 
460
                                error_reason("Write error");
 
461
                        free(buffer);
 
462
                        return -1;
 
463
                }
 
464
        }
 
465
        free(buffer);
 
466
        return 0;
 
467
}
 
468
 
 
469
 
 
470
/* Write COUNT tapemarks to file handle FD. */
 
471
static int
 
472
write_tapemark(int fd, int count)
 
473
{
 
474
        struct mtop op;
 
475
 
 
476
        op.mt_count = count;
 
477
        op.mt_op = MTWEOF;
 
478
        if (ioctl(fd, MTIOCTOP, &op) == -1) {
 
479
                error_reason("Could not write tapemark");
 
480
                return -1;
 
481
        }
 
482
        return 0;
 
483
}
 
484
 
 
485
 
 
486
#define IPL_TAPE_BLOCKSIZE      1024
 
487
 
 
488
/* Install IPL record on tape device. */
 
489
int
 
490
install_tapeloader(const char* device, const char* image, const char* parmline,
 
491
                   const char* ramdisk, address_t image_addr,
 
492
                   address_t parm_addr, address_t initrd_addr)
 
493
{
 
494
        void* buffer;
 
495
        size_t size;
 
496
        int rc;
 
497
        int fd;
 
498
 
 
499
        printf("Preparing boot tape: %s\n", device);
 
500
        /* Prepare boot loader */
 
501
        rc = boot_get_tape_ipl(&buffer, &size, parm_addr, initrd_addr,
 
502
                               image_addr);
 
503
        if (rc)
 
504
                return rc;
 
505
        /* Open device */
 
506
        fd = open(device, O_RDWR);
 
507
        if (fd == -1) {
 
508
                error_reason(strerror(errno));
 
509
                error_text("Could not open tape device '%s'", device);
 
510
                free(buffer);
 
511
                return -1;
 
512
        }
 
513
        if (rewind_tape(fd) != 0) {
 
514
                error_text("Could not rewind tape device '%s'", device);
 
515
                free(buffer);
 
516
                close(fd);
 
517
                return -1;
 
518
        }
 
519
        /* Write boot loader */
 
520
        rc = write_tapebuffer(fd, buffer, size, IPL_TAPE_BLOCKSIZE);
 
521
        free(buffer);
 
522
        if (rc) {
 
523
                error_text("Could not write boot loader to tape");
 
524
                close(fd);
 
525
                return rc;
 
526
        }
 
527
        rc = write_tapemark(fd, 1);
 
528
        if (rc) {
 
529
                error_text("Could not write boot loader to tape");
 
530
                close(fd);
 
531
                return rc;
 
532
        }
 
533
        /* Write image file */
 
534
        if (verbose) {
 
535
                printf("  kernel image......: %s at 0x%llx\n", image,
 
536
                       (unsigned long long) image_addr);
 
537
        }
 
538
        rc = write_tapefile(fd, image, IPL_TAPE_BLOCKSIZE);
 
539
        if (rc) {
 
540
                error_text("Could not write image file '%s' to tape", image);
 
541
                close(fd);
 
542
                return rc;
 
543
        }
 
544
        rc = write_tapemark(fd, 1);
 
545
        if (rc) {
 
546
                error_text("Could not write boot loader to tape");
 
547
                close(fd);
 
548
                return rc;
 
549
        }
 
550
        if (parmline != NULL) {
 
551
                if (verbose) {
 
552
                        printf("  kernel parmline...: '%s' at 0x%llx\n",
 
553
                               parmline, (unsigned long long) parm_addr);
 
554
                }
 
555
                /* Write parameter line */
 
556
                rc = write_tapebuffer(fd, parmline, strlen(parmline),
 
557
                                      IPL_TAPE_BLOCKSIZE);
 
558
                if (rc) {
 
559
                        error_text("Could not write parameter string to tape");
 
560
                        close(fd);
 
561
                        return rc;
 
562
                }
 
563
        }
 
564
        rc = write_tapemark(fd, 1);
 
565
        if (rc) {
 
566
                error_text("Could not write boot loader to tape");
 
567
                close(fd);
 
568
                return rc;
 
569
        }
 
570
        if (ramdisk != NULL) {
 
571
                /* Write ramdisk */
 
572
                if (verbose) {
 
573
                        printf("  initial ramdisk...: %s at 0x%llx\n",
 
574
                               ramdisk, (unsigned long long) initrd_addr);
 
575
                }
 
576
                rc = write_tapefile(fd, ramdisk, IPL_TAPE_BLOCKSIZE);
 
577
                if (rc) {
 
578
                        error_text("Could not write ramdisk file '%s' to tape",
 
579
                                   ramdisk);
 
580
                        close(fd);
 
581
                        return rc;
 
582
                }
 
583
        }
 
584
        rc = write_tapemark(fd, 1);
 
585
        if (rc) {
 
586
                error_text("Could not write boot loader to tape");
 
587
                close(fd);
 
588
                return rc;
 
589
        }
 
590
        if (rewind_tape(fd) != 0) {
 
591
                error_text("Could not rewind tape device '%s' to tape", device);
 
592
                rc = -1;
 
593
        }
 
594
        close(fd);
 
595
        return rc;
 
596
}
 
597
 
 
598
 
 
599
struct eckd_dump_param {
 
600
        uint16_t        cyl;
 
601
        uint16_t        head;
 
602
        uint8_t         sec;
 
603
        uint16_t        blocksize;
 
604
        uint8_t         num_heads;
 
605
} __attribute((packed));
 
606
 
 
607
static int
 
608
install_dump_eckd_classic(int fd, struct disk_info* info, uint64_t mem)
 
609
{
 
610
        struct boot_eckd_stage0 stage0;
 
611
        struct boot_eckd_classic_stage1 stage1;
 
612
        struct eckd_dump_param* param;
 
613
        void* buffer;
 
614
        size_t size;
 
615
        int rc;
 
616
 
 
617
        /* Prepare stage 0 */
 
618
        boot_init_eckd_classic_stage0(&stage0);
 
619
        /* Install stage 0 */
 
620
        rc = misc_write(fd, &stage0, sizeof(struct boot_eckd_stage0));
 
621
        if (rc) {
 
622
                error_text("Could not write boot loader");
 
623
                return rc;
 
624
        }
 
625
        /* Prepare stage 1 */
 
626
        rc = boot_init_eckd_classic_dump_stage1(&stage1, info);
 
627
        if (rc)
 
628
                return rc;
 
629
        /* Fill in start of dump partition */
 
630
        param = (struct eckd_dump_param *) &stage1.param1;
 
631
        param->cyl = disk_cyl_from_blocknum(info->geo.start, info);
 
632
        param->head = disk_head_from_blocknum(info->geo.start, info);
 
633
        param->sec = disk_sec_from_blocknum(info->geo.start, info);
 
634
        param->blocksize = info->phy_block_size;
 
635
        param->num_heads = info->geo.heads;
 
636
        /* Fill in end of dump partition. Note that on ECKD devices with
 
637
         * classic disk layout, there is exactly one partition so that the
 
638
         * end of the device equals the end of the partition. */
 
639
        param = (struct eckd_dump_param *) &stage1.param2;
 
640
        param->cyl = info->geo.cylinders - 1;
 
641
        param->head = info->geo.heads - 1;
 
642
        param->sec = info->geo.sectors;
 
643
        param->blocksize = info->phy_block_size;
 
644
        param->num_heads = 0; /* Unused */
 
645
        /* Install stage 1 */
 
646
        if (lseek(fd, info->phy_block_size, SEEK_SET) !=
 
647
            info->phy_block_size) {
 
648
                error_reason(strerror(errno));
 
649
                error_text("Could not seek on device");
 
650
                return -1;
 
651
        }
 
652
        rc = misc_write(fd, &stage1, sizeof(struct boot_eckd_classic_stage1));
 
653
        if (rc) {
 
654
                error_text("Could not write dump record");
 
655
                return rc;
 
656
        }
 
657
        /* Install stage 2 dump record at beginning of partition */
 
658
        if (lseek(fd, info->geo.start * info->phy_block_size, SEEK_SET) !=
 
659
            (off_t) info->geo.start * info->phy_block_size) {
 
660
                error_text("Could not seek on device");
 
661
                return -1;
 
662
        }
 
663
        rc = boot_get_eckd_dump_stage2(&buffer, &size, mem);
 
664
        if (rc)
 
665
                return rc;
 
666
        rc = misc_write(fd, buffer, size);
 
667
        if (rc)
 
668
                error_text("Could not write dump record");
 
669
        free(buffer);
 
670
        return rc;
 
671
}
 
672
 
 
673
 
 
674
static int
 
675
install_dump_eckd_compatible(int fd, struct disk_info* info, uint64_t mem)
 
676
{
 
677
        struct boot_eckd_stage0 stage0;
 
678
        struct boot_eckd_compatible_stage1 stage1;
 
679
        struct eckd_dump_param* param;
 
680
        void* buffer;
 
681
        size_t size;
 
682
        int rc;
 
683
 
 
684
        /* Prepare stage 0 */
 
685
        boot_init_eckd_compatible_stage0(&stage0);
 
686
        /* Install stage 0 */
 
687
        if (lseek(fd, 4, SEEK_SET) != 4) {
 
688
                error_reason(strerror(errno));
 
689
                error_text("Could not seek on device");
 
690
                return -1;
 
691
        }
 
692
        rc = misc_write(fd, &stage0, sizeof(struct boot_eckd_stage0));
 
693
        if (rc) {
 
694
                error_text("Could not write boot loader");
 
695
                return rc;
 
696
        }
 
697
        /* Prepare stage 1 */
 
698
        rc = boot_init_eckd_compatible_dump_stage1(&stage1, info);
 
699
        if (rc)
 
700
                return rc;
 
701
        /* Fill in start of dump partition */
 
702
        param = (struct eckd_dump_param *) &stage1.param1;
 
703
        param->cyl = disk_cyl_from_blocknum(info->geo.start, info);
 
704
        param->head = disk_head_from_blocknum(info->geo.start, info);
 
705
        param->sec = disk_sec_from_blocknum(info->geo.start, info);
 
706
        param->blocksize = info->phy_block_size;
 
707
        param->num_heads = info->geo.heads;
 
708
        /* Fill in end of dump partition. */
 
709
        param = (struct eckd_dump_param *) &stage1.param2;
 
710
        param->cyl = disk_cyl_from_blocknum(info->geo.start +
 
711
                                            info->phy_blocks - 1, info);
 
712
        param->head = disk_head_from_blocknum(info->geo.start +
 
713
                                              info->phy_blocks - 1, info);
 
714
        param->sec = disk_sec_from_blocknum(info->geo.start +
 
715
                                            info->phy_blocks - 1, info);
 
716
        param->blocksize        = info->phy_block_size;
 
717
        param->num_heads        = 0; /* Unused */
 
718
        /* Install stage 1 */
 
719
        if (lseek(fd, info->phy_block_size + 4, SEEK_SET) !=
 
720
            info->phy_block_size + 4) {
 
721
                error_reason(strerror(errno));
 
722
                error_text("Could not seek on device");
 
723
                return -1;
 
724
        }
 
725
        rc = misc_write(fd, &stage1,
 
726
                        sizeof(struct boot_eckd_compatible_stage1));
 
727
        if (rc) {
 
728
                error_text("Could not write dump record");
 
729
                return rc;
 
730
        }
 
731
        /* Install stage 2 dump record */
 
732
        if (lseek(fd, 3 * info->phy_block_size, SEEK_SET) !=
 
733
            3 * info->phy_block_size) {
 
734
                error_text("Could not seek on device");
 
735
                return -1;
 
736
        }
 
737
        rc = boot_get_eckd_dump_stage2(&buffer, &size, mem);
 
738
        if (rc)
 
739
                return rc;
 
740
        rc = misc_write(fd, buffer, size);
 
741
        if (rc)
 
742
                error_text("Could not write dump record");
 
743
        free(buffer);
 
744
        return rc;
 
745
}
 
746
 
 
747
 
 
748
static int
 
749
install_dump_tape(int fd, uint64_t mem)
 
750
{
 
751
        void* buffer;
 
752
        size_t size;
 
753
        int rc;
 
754
 
 
755
        rc = boot_get_tape_dump(&buffer, &size, mem);
 
756
        if (rc)
 
757
                return rc;
 
758
        rc = misc_write(fd, buffer, size);
 
759
        if (rc)
 
760
                error_text("Could not write to tape device");
 
761
        free(buffer);
 
762
        return 0;
 
763
}
 
764
 
 
765
 
 
766
int
 
767
install_dump(const char* device, uint64_t mem)
 
768
{
 
769
        struct disk_info* info;
 
770
        char* tempdev;
 
771
        int fd;
 
772
        int rc;
 
773
 
 
774
        fd = open(device, O_RDWR);
 
775
        if (fd == -1) {
 
776
                error_reason(strerror(errno));
 
777
                error_text("Could not open dump device '%s'", device);
 
778
                return -1;
 
779
        }
 
780
        if (rewind_tape(fd) == 0) {
 
781
                /* Rewind worked - this is a tape */
 
782
                rc = ask_for_confirmation("Warning: All information on device "
 
783
                                          "'%s' will be lost!\nDo you want to "
 
784
                                          "continue creating a one-shot dump "
 
785
                                          "tape (y/n) ?", device);
 
786
                if (rc) {
 
787
                        close(fd);
 
788
                        return rc;
 
789
                }
 
790
                if (verbose)
 
791
                        printf("Installing tape dump record\n");
 
792
                rc = install_dump_tape(fd, mem);
 
793
                if (rc) {
 
794
                        error_text("Could not install dump record on tape "
 
795
                                   "device '%s'", device);
 
796
                } else {
 
797
                        if (verbose) {
 
798
                                printf("Dump record successfully installed on "
 
799
                                       "tape device '%s'.\n", device);
 
800
                        }
 
801
                }
 
802
                close(fd);
 
803
                return rc;
 
804
        }
 
805
        close(fd);
 
806
        /* This is a disk device */
 
807
        rc = disk_get_info(device, &info);
 
808
        if (rc) {
 
809
                error_text("Could not get information for dump target "
 
810
                           "'%s'", device);
 
811
                close(fd);
 
812
                return rc;
 
813
        }
 
814
        if (info->partnum == 0) {
 
815
                error_reason("Dump target '%s' is not a disk partition",
 
816
                             device);
 
817
                disk_free_info(info);
 
818
                return -1;
 
819
        }
 
820
        if (verbose) {
 
821
                printf("Target device information\n");
 
822
                disk_print_info(info);
 
823
        }
 
824
        rc = misc_temp_dev(info->device, 1, &tempdev);
 
825
        if (rc) {
 
826
                disk_free_info(info);
 
827
                return -1;
 
828
        }
 
829
        fd = open(tempdev, O_RDWR);
 
830
        if (fd == -1) {
 
831
                error_text("Could not open temporary device node '%s'",
 
832
                           tempdev);
 
833
                misc_free_temp_dev(tempdev);
 
834
                disk_free_info(info);
 
835
                return -1;
 
836
        }
 
837
        switch (info->type) {
 
838
        case disk_type_eckd_classic:
 
839
        case disk_type_eckd_compatible:
 
840
                rc = ask_for_confirmation("Warning: All information on "
 
841
                                          "partition '%s' will be lost!\n"
 
842
                                          "Do you want to continue creating "
 
843
                                          "a dump partition (y/n)?", device);
 
844
                if (rc)
 
845
                        break;
 
846
                if (verbose) {
 
847
                        printf("Installing dump record on partition with %s\n",
 
848
                               disk_get_type_name(info->type));
 
849
                }
 
850
                if (info->type == disk_type_eckd_classic)
 
851
                        rc = install_dump_eckd_classic(fd, info, mem);
 
852
                else
 
853
                        rc = install_dump_eckd_compatible(fd, info, mem);
 
854
                break;
 
855
        case disk_type_scsi:
 
856
        case disk_type_fba:
 
857
        case disk_type_diag:
 
858
        case disk_type_unknown:
 
859
                error_reason("Unsupported disk type '%s' of dump target '%s'",
 
860
                             disk_get_type_name(info->type), device);
 
861
                rc = -1;
 
862
                break;
 
863
        }
 
864
        misc_free_temp_dev(tempdev);
 
865
        disk_free_info(info);
 
866
        close(fd);
 
867
        return rc;
 
868
}