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

« back to all changes in this revision

Viewing changes to zipl/src/boot.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2004-06-27 18:45:15 UTC
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20040627184515-q7lnvli1j94gr6dv
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * s390-tools/zipl/src/boot.c
 
3
 *   Functions to handle the boot loader data.
 
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 "boot.h"
 
12
 
 
13
#include <stdint.h>
 
14
#include <string.h>
 
15
#include <stdio.h>
 
16
#include <stdlib.h>
 
17
 
 
18
#include "bootmap.h"
 
19
#include "error.h"
 
20
#include "misc.h"
 
21
 
 
22
/* Include boot data */
 
23
#include "../boot/data.c"
 
24
 
 
25
#define STAGE2_MAX_SIZE         4096
 
26
 
 
27
 
 
28
/* Check sizes of internal objects. Return 0 if everything is correct,
 
29
 * non-zero otherwise. */
 
30
int
 
31
boot_check_data(void)
 
32
{
 
33
        if (sizeof(boot_data_fba0) !=
 
34
            sizeof(struct boot_fba_stage0)) {
 
35
                error_reason("Size mismatch of stage 0 loader for disks with "
 
36
                             "FBA layout");
 
37
                return -1;
 
38
        }
 
39
        if (sizeof(boot_data_eckd0) !=
 
40
            sizeof(struct boot_eckd_stage0)) {
 
41
                error_reason("Size mismatch of stage 0 loader for disks with "
 
42
                             "ECKD layout");
 
43
                return -1;
 
44
        }
 
45
        if (sizeof(boot_data_eckd1a) !=
 
46
            sizeof(struct boot_eckd_classic_stage1)) {
 
47
                error_reason("Size mismatch of stage 1 loader for disks with "
 
48
                             "ECKD classic layout");
 
49
                return -1;
 
50
        }
 
51
        if (sizeof(boot_data_eckd1b) !=
 
52
            sizeof(struct boot_eckd_compatible_stage1)) {
 
53
                error_reason("Size mismatch of stage 1 loader for disks with "
 
54
                             "ECKD compatible layout");
 
55
                return -1;
 
56
        }
 
57
        return 0;
 
58
}
 
59
 
 
60
 
 
61
/* Create a stage 3 loader in memory.
 
62
 * Upon success, return 0 and set BUFFER to point to the data buffer and set
 
63
 * BYTECOUNT to contain the loader size in bytes. Return non-zero otherwise. */
 
64
int
 
65
boot_get_stage3(void** buffer, size_t* bytecount, address_t parm_addr,
 
66
                address_t initrd_addr, size_t initrd_len, address_t image_addr,
 
67
                int extra_parm)
 
68
{
 
69
        struct boot_stage3_params params;
 
70
        void* data;
 
71
 
 
72
        if (image_addr != (image_addr & PSW_ADDRESS_MASK)) {
 
73
                error_reason("Kernel image load address to high (31 bit "
 
74
                             "addressing mode)");
 
75
                return -1;
 
76
        }
 
77
        /* Get memory */
 
78
        data = misc_malloc(sizeof(boot_data_stage3));
 
79
        if (data == NULL)
 
80
                return -1;
 
81
        /* Prepare params section */
 
82
        params.parm_addr = (uint64_t) parm_addr;
 
83
        params.initrd_addr = (uint64_t) initrd_addr;
 
84
        params.initrd_len = (uint64_t) initrd_len;
 
85
        params.load_psw = (uint64_t) (image_addr | PSW_LOAD);
 
86
        params.extra_parm = (uint64_t) extra_parm;
 
87
        /* Initialize buffer */
 
88
        memcpy(data, boot_data_stage3, sizeof(boot_data_stage3));
 
89
        memcpy(data, &params, sizeof(struct boot_stage3_params));
 
90
        *buffer = data;
 
91
        *bytecount = sizeof(boot_data_stage3);
 
92
        return 0;
 
93
}
 
94
 
 
95
 
 
96
#define FBA_FLAG_CC 0x0000000040000000LL
 
97
 
 
98
int
 
99
boot_init_fba_stage0(struct boot_fba_stage0* stage0,
 
100
                     disk_blockptr_t* program_table,
 
101
                     disk_blockptr_t* stage2_list, blocknum_t stage2_count,
 
102
                     struct disk_info* info)
 
103
{
 
104
        blocknum_t i;
 
105
 
 
106
        /* Initialize stage 0 data */
 
107
        memcpy(stage0, boot_data_fba0, sizeof(struct boot_fba_stage0));
 
108
        /* Fill in blocklist for stage 2 loader */
 
109
        if (stage2_count > 8) {
 
110
                error_reason("Not enough room for FBA stage 2 loader "
 
111
                             "(try larger block size)");
 
112
                return -1;
 
113
        }
 
114
        for (i=0; i < stage2_count; i++) {
 
115
                stage0->locdata[i].blocknr =
 
116
                        (uint32_t) stage2_list[i].linear.block;
 
117
        }
 
118
        /* Terminate CCW chain */
 
119
        stage0->locread[i - 1].read &= ~FBA_FLAG_CC;
 
120
        /* Store program table pointer in stage 0 loader */
 
121
        bootmap_store_blockptr(&stage0->param1, program_table, info);
 
122
        return 0;
 
123
}
 
124
 
 
125
 
 
126
void
 
127
boot_init_eckd_classic_stage0(struct boot_eckd_stage0* stage0)
 
128
{
 
129
        memcpy(stage0, boot_data_eckd0, sizeof(struct boot_eckd_stage0));
 
130
        /* Fill in size of stage 1 loader */
 
131
        stage0->read.count = sizeof(struct boot_eckd_classic_stage1);
 
132
}
 
133
 
 
134
 
 
135
void
 
136
boot_init_eckd_compatible_stage0(struct boot_eckd_stage0* stage0)
 
137
{
 
138
        memcpy(stage0, boot_data_eckd0, sizeof(struct boot_eckd_stage0));
 
139
        /* Fill in size of stage 1 loader */
 
140
        stage0->read.count = sizeof(struct boot_eckd_compatible_stage1);
 
141
}
 
142
 
 
143
 
 
144
#define ECKD_CCW_FLAG_CC        0x40
 
145
#define ECKD_CCW_FLAG_SLI       0x20
 
146
 
 
147
int
 
148
boot_init_eckd_classic_stage1(struct boot_eckd_classic_stage1* stage1,
 
149
                     disk_blockptr_t* stage2_list, blocknum_t stage2_count,
 
150
                     struct disk_info* info)
 
151
{
 
152
        blocknum_t i;
 
153
 
 
154
        memcpy(stage1, boot_data_eckd1a,
 
155
               sizeof(struct boot_eckd_classic_stage1));
 
156
        /* Fill in blocklist for stage 2 loader */
 
157
        if (stage2_count > 8) {
 
158
                error_reason("Not enough room for ECKD stage 2 loader "
 
159
                             "(try larger block size)");
 
160
                return -1;
 
161
        }
 
162
        for (i=0; i < stage2_count; i++) {
 
163
                stage1->ssrt[i].read.count      = stage2_list[i].chs.size;
 
164
                stage1->seek[i].cyl             = stage2_list[i].chs.cyl;
 
165
                stage1->seek[i].head            = stage2_list[i].chs.head;
 
166
                stage1->seek[i].sec             = stage2_list[i].chs.sec;
 
167
                stage1->ssrt[i].read.address_lo = ZIPL_STAGE2_LOAD_ADDRESS +
 
168
                                                  i * stage2_list[i].chs.size;
 
169
                stage1->ssrt[i].read.flags      = ECKD_CCW_FLAG_CC |
 
170
                                                  ECKD_CCW_FLAG_SLI;
 
171
        }
 
172
        /* Terminate CCW chain */
 
173
        stage1->ssrt[i - 1].read.flags &= ~ECKD_CCW_FLAG_CC;
 
174
        return 0;
 
175
}
 
176
 
 
177
 
 
178
int
 
179
boot_init_eckd_classic_dump_stage1(struct boot_eckd_classic_stage1* stage1,
 
180
                                   struct disk_info* info)
 
181
{
 
182
        blocknum_t blocks;
 
183
        blocknum_t i;
 
184
 
 
185
        memcpy(stage1, boot_data_eckd1a,
 
186
               sizeof(struct boot_eckd_classic_stage1));
 
187
        blocks = (sizeof(boot_data_eckd2dump) +
 
188
                        info->phy_block_size - 1) / info->phy_block_size;
 
189
        if (blocks > 8) {
 
190
                error_reason("Not enough room for ECKD stage 2 dump record "
 
191
                             "(try larger block size)");
 
192
                return -1;
 
193
        }
 
194
        /* Fill in block list of stage 2 dump record */
 
195
        for (i=0; i < blocks; i++) {
 
196
                stage1->ssrt[i].read.count = info->phy_block_size;
 
197
                stage1->ssrt[i].read.address_lo = ZIPL_STAGE2_LOAD_ADDRESS +
 
198
                                                  i * info->phy_block_size;
 
199
                stage1->seek[i].cyl =
 
200
                        disk_cyl_from_blocknum(i + info->geo.start, info);
 
201
                stage1->seek[i].head =
 
202
                        disk_head_from_blocknum(i + info->geo.start, info);
 
203
                stage1->seek[i].sec =
 
204
                        disk_sec_from_blocknum(i + info->geo.start, info);
 
205
        }
 
206
        /* Terminate CCW chain */
 
207
        stage1->ssrt[i - 1].read.flags &= ~ECKD_CCW_FLAG_CC;
 
208
        return 0;
 
209
}
 
210
 
 
211
 
 
212
int
 
213
boot_init_eckd_compatible_stage1(struct boot_eckd_compatible_stage1* stage1,
 
214
                                 struct disk_info* info)
 
215
{
 
216
        blocknum_t blocks;
 
217
        blocknum_t i;
 
218
 
 
219
        memcpy(stage1, boot_data_eckd1b,
 
220
               sizeof(struct boot_eckd_compatible_stage1));
 
221
        /* Fill in blocklist for stage 2 loader */
 
222
        blocks = (STAGE2_MAX_SIZE + info->phy_block_size - 1) /
 
223
                 info->phy_block_size;
 
224
        if (blocks > 12) {
 
225
                error_reason("Not enough room for ECKD stage 2 loader "
 
226
                             "(try larger block size)");
 
227
                return -1;
 
228
        }
 
229
        for (i=0; i < blocks; i++) {
 
230
                stage1->read[i].count           = info->phy_block_size;
 
231
                stage1->read[i].address_lo      = ZIPL_STAGE2_LOAD_ADDRESS +
 
232
                                                  i * info->phy_block_size;
 
233
        }
 
234
        /* Terminate CCW chain */
 
235
        stage1->read[i - 1].flags &= ~ECKD_CCW_FLAG_CC;
 
236
        return 0;
 
237
}
 
238
 
 
239
 
 
240
int
 
241
boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr,
 
242
                  address_t initrd_addr, address_t image_addr)
 
243
{
 
244
        struct boot_tape_ipl_params params;
 
245
        void* buffer;
 
246
 
 
247
        if (image_addr != (image_addr & PSW_ADDRESS_MASK)) {
 
248
                error_reason("Kernel image load address to high (31 bit "
 
249
                             "addressing mode)");
 
250
                return -1;
 
251
        }
 
252
        buffer = misc_malloc(sizeof(boot_data_tape0));
 
253
        if (buffer == NULL)
 
254
                return -1;
 
255
        /* Prepare params section */
 
256
        params.parm_addr = (uint64_t) parm_addr;
 
257
        params.initrd_addr = (uint64_t) initrd_addr;
 
258
        params.load_psw = (uint64_t) (image_addr | PSW_LOAD);
 
259
        /* Initialize buffer */
 
260
        memcpy(buffer, boot_data_tape0, sizeof(boot_data_tape0));
 
261
        memcpy(VOID_ADD(buffer, BOOT_TAPE_IPL_PARAMS_OFFSET), &params,
 
262
               sizeof(struct boot_tape_ipl_params));
 
263
        *data = buffer;
 
264
        *size = sizeof(boot_data_tape0);
 
265
        return 0;
 
266
}
 
267
 
 
268
 
 
269
int
 
270
boot_init_eckd_compatible_dump_stage1(
 
271
                                struct boot_eckd_compatible_stage1* stage1,
 
272
                                struct disk_info* info)
 
273
{
 
274
        blocknum_t blocks;
 
275
        blocknum_t i;
 
276
 
 
277
        memcpy(stage1, boot_data_eckd1b,
 
278
               sizeof(struct boot_eckd_compatible_stage1));
 
279
        blocks = (sizeof(boot_data_eckd2dump) +
 
280
                        info->phy_block_size - 1) / info->phy_block_size;
 
281
        if (blocks > 12) {
 
282
                error_reason("Not enough room for ECKD stage 2 dump record "
 
283
                             "(try larger block size)");
 
284
                return -1;
 
285
        }
 
286
        /* Fill in block list of stage 2 dump record */
 
287
        for (i = 0; i < blocks; i++) {
 
288
                stage1->read[i].count = info->phy_block_size;
 
289
                stage1->read[i].address_lo = ZIPL_STAGE2_LOAD_ADDRESS +
 
290
                                             i * info->phy_block_size;
 
291
        }
 
292
        /* Terminate CCW chain */
 
293
        stage1->read[i - 1].flags &= ~ECKD_CCW_FLAG_CC;
 
294
        return 0;
 
295
}
 
296
 
 
297
 
 
298
/* ASCII to EBCDIC conversion table. */
 
299
unsigned char ascebc[256] =
 
300
{
 
301
     0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
 
302
     0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
 
303
     0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
 
304
     0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
 
305
     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
 
306
     0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
 
307
     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
 
308
     0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
 
309
     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
 
310
     0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
 
311
     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
 
312
     0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
 
313
     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
 
314
     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
 
315
     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
 
316
     0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
 
317
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
318
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
319
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
320
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
321
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
322
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
323
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
324
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
325
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
326
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
327
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
328
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
329
     0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
330
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
331
     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
 
332
     0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
 
333
};
 
334
 
 
335
static void ascii_to_ebcdic(unsigned char* from, unsigned char* to)
 
336
{
 
337
        for (;from != to; from++)
 
338
                *from = ascebc[*from];
 
339
}
 
340
 
 
341
 
 
342
static int
 
343
store_stage2_menu(void* data, size_t size, struct job_data* job)
 
344
{
 
345
        struct boot_stage2_params* params;
 
346
        char* current;
 
347
        char* name;
 
348
        ssize_t len;
 
349
        int flag;
 
350
        int timeout;
 
351
        int textlen;
 
352
        int maxlen;
 
353
        int i;
 
354
 
 
355
        memset(data, 0, size);
 
356
        if (job->id == job_menu) {
 
357
                name = "-";
 
358
                for (i=0; i < job->data.menu.num; i++)
 
359
                        if (job->data.menu.entry[i].pos ==
 
360
                            job->data.menu.default_pos)
 
361
                                name = job->data.menu.entry[i].name;
 
362
                flag = (job->data.menu.prompt != 0);
 
363
                timeout = job->data.menu.timeout;
 
364
                /* Be verbose */
 
365
                if (verbose) {
 
366
                        printf("Preparing boot menu\n");
 
367
                        printf("  Interactive prompt......: %s\n",
 
368
                               job->data.menu.prompt ? "enabled" : "disabled");
 
369
                        if (job->data.menu.timeout == 0)
 
370
                                printf("  Menu timeout............: "
 
371
                                       "disabled\n");
 
372
                        else
 
373
                                printf("  Menu timeout............: %d "
 
374
                                       "seconds\n", job->data.menu.timeout);
 
375
                        printf("  Default configuration...: '%s'\n", name);
 
376
                }
 
377
        } else {
 
378
                name = job->name;
 
379
                flag = 0;
 
380
                timeout = 0;
 
381
        }
 
382
        /* Header */
 
383
        len = sizeof(struct boot_stage2_params);
 
384
        if (size < len) {
 
385
                error_reason("Not enough room for menu data");
 
386
                return -1;
 
387
        }
 
388
        params = (struct boot_stage2_params *) data;
 
389
        params->flag = flag;
 
390
        params->timeout = timeout;
 
391
        current = (char *) (params + 1);
 
392
        size -= len;
 
393
        /* Banner text */
 
394
        len = snprintf(current, size, "zIPL v%s interactive boot menu\n ",
 
395
                       RELEASE_STRING) + 1;
 
396
        if (len >= size) {
 
397
                error_reason("Not enough room for menu data");
 
398
                return -1;
 
399
        }
 
400
        params->banner = (uint16_t) ((unsigned long) current -
 
401
                                     (unsigned long) data);
 
402
        current += len;
 
403
        size -= len;
 
404
        /* Default config text */
 
405
        if (name != NULL)
 
406
                len = snprintf(current, size, " 0. default (%s)", name) + 1;
 
407
        else
 
408
                len = snprintf(current, size, " 0. default") + 1;
 
409
        if (len >= size) {
 
410
                error_reason("Not enough room for menu data");
 
411
                return -1;
 
412
        }
 
413
        params->config[0] = (uint16_t) ((unsigned long) current -
 
414
                                        (unsigned long) data);
 
415
        current += len;
 
416
        size -= len;
 
417
        /* Skip rest if job is not an actual menu */
 
418
        if (job->id != job_menu) {
 
419
                /* Convert to EBCDIC */
 
420
                ascii_to_ebcdic((unsigned char *) (params + 1),
 
421
                                (unsigned char *) current);
 
422
                return 0;
 
423
        }
 
424
        /* Config texts */
 
425
        textlen = 0;
 
426
        maxlen = 0;
 
427
        for (i = 0; i < job->data.menu.num; i++) {
 
428
                len = strlen(job->data.menu.entry[i].name);
 
429
                if (len > maxlen)
 
430
                        maxlen = len;
 
431
                textlen += len + 1;
 
432
        }
 
433
        maxlen += 5; /* '%2d. \0' */
 
434
        if (textlen > size) {
 
435
                /* Menu text won't fit, need to truncate */
 
436
                maxlen = size / job->data.menu.num;
 
437
                if (maxlen < 6) {
 
438
                        error_reason("Not enough room for menu data (try "
 
439
                                     "shorter config names)");
 
440
                        return -1;
 
441
                }
 
442
                fprintf(stderr, "Warning: Menu text too large, truncating "
 
443
                        "names at %d characters!\n", maxlen - 5);
 
444
        }
 
445
        for (i = 0; i < job->data.menu.num; i++) {
 
446
                len = snprintf(current, maxlen, "%2d. %s",
 
447
                               job->data.menu.entry[i].pos,
 
448
                               job->data.menu.entry[i].name) + 1;
 
449
                if (len > maxlen)
 
450
                        len = maxlen;
 
451
                params->config[job->data.menu.entry[i].pos] = (uint16_t)
 
452
                        ((unsigned long) current - (unsigned long) data);
 
453
                current += len;
 
454
        }
 
455
        /* Convert to EBCDIC */
 
456
        ascii_to_ebcdic((unsigned char *) (params + 1),
 
457
                        (unsigned char *) current);
 
458
        return 0;
 
459
}
 
460
 
 
461
 
 
462
 
 
463
int
 
464
boot_get_fba_stage2(void** data, size_t* size, struct job_data* job)
 
465
{
 
466
        void* buffer;
 
467
        int rc;
 
468
 
 
469
        buffer = misc_malloc(STAGE2_MAX_SIZE);
 
470
        if (buffer == NULL)
 
471
                return -1;
 
472
        memcpy(buffer, boot_data_fba2, sizeof(boot_data_fba2));
 
473
        rc = store_stage2_menu(VOID_ADD(buffer, sizeof(boot_data_fba2)),
 
474
                               STAGE2_MAX_SIZE - sizeof(boot_data_fba2),
 
475
                               job);
 
476
        if (rc) {
 
477
                free(buffer);
 
478
                return rc;
 
479
        }
 
480
        *data = buffer;
 
481
        *size = STAGE2_MAX_SIZE;
 
482
        return 0;
 
483
}
 
484
 
 
485
 
 
486
int
 
487
boot_get_eckd_stage2(void** data, size_t* size, struct job_data* job)
 
488
{
 
489
        void* buffer;
 
490
        int rc;
 
491
 
 
492
        buffer = misc_malloc(STAGE2_MAX_SIZE);
 
493
        if (buffer == NULL)
 
494
                return -1;
 
495
        memcpy(buffer, boot_data_eckd2, sizeof(boot_data_eckd2));
 
496
        rc = store_stage2_menu(VOID_ADD(buffer, sizeof(boot_data_eckd2)),
 
497
                               STAGE2_MAX_SIZE - sizeof(boot_data_eckd2),
 
498
                               job);
 
499
        if (rc) {
 
500
                free(buffer);
 
501
                return rc;
 
502
        }
 
503
        *data = buffer;
 
504
        *size = STAGE2_MAX_SIZE;
 
505
        return 0;
 
506
}
 
507
 
 
508
 
 
509
int
 
510
boot_get_tape_dump(void** data, size_t* size, uint64_t mem)
 
511
{
 
512
        void* buffer;
 
513
 
 
514
        buffer = misc_malloc(sizeof(boot_data_tapedump));
 
515
        if (buffer == NULL)
 
516
                return -1;
 
517
        memcpy(buffer, boot_data_tapedump, sizeof(boot_data_tapedump));
 
518
        /* Write mem size to end of dump record */
 
519
        memcpy(VOID_ADD(buffer, sizeof(boot_data_tapedump) - sizeof(mem)), &mem,
 
520
               sizeof(mem));
 
521
        *data = buffer;
 
522
        *size = sizeof(boot_data_tapedump);
 
523
        return 0;
 
524
}
 
525
 
 
526
 
 
527
int
 
528
boot_get_eckd_dump_stage2(void** data, size_t* size, uint64_t mem)
 
529
{
 
530
        void* buffer;
 
531
 
 
532
        buffer = misc_malloc(sizeof(boot_data_eckd2dump));
 
533
        if (buffer == NULL)
 
534
                return -1;
 
535
        memcpy(buffer, boot_data_eckd2dump, sizeof(boot_data_eckd2dump));
 
536
        /* Write mem size to end of dump record */
 
537
        memcpy(VOID_ADD(buffer, sizeof(boot_data_eckd2dump) - sizeof(mem)),
 
538
               &mem, sizeof(mem));
 
539
        *data = buffer;
 
540
        *size = sizeof(boot_data_eckd2dump);
 
541
        return 0;
 
542
}