Import version 1.8.3
[s390-tools.git] / zipl / src / zipl.c
blobdd583801dc4bd7d9e6e02db93961f9d3f4e92883
1 /*
2 * s390-tools/zipl/src/zipl.c
3 * zSeries Initial Program Loader tool.
5 * Copyright IBM Corp. 2001, 2009.
7 * Author(s): Carsten Otte <cotte@de.ibm.com>
8 * Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>
9 */
11 #include "zipl.h"
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
21 #include "boot.h"
22 #include "bootmap.h"
23 #include "disk.h"
24 #include "error.h"
25 #include "install.h"
26 #include "job.h"
27 #include "misc.h"
28 #include "zt_common.h"
31 /* Flag deciding the level of verbosity */
32 int verbose = 0;
34 /* Flag deciding whether confirmation questions are asked */
35 int interactive = 1;
37 /* Flag deciding whether actions should only be simulated */
38 int dry_run = 1;
40 /* Full tool name */
41 static const char tool_name[] = "zipl: zSeries Initial Program Loader";
43 /* Copyright notice */
44 static const char copyright_notice[] = "Copyright IBM Corp. 2001, 2009";
46 /* Usage information */
47 static const char* usage_text[] = {
48 "Usage: zipl [OPTIONS] [SECTION]",
49 "",
50 "Prepare a device for initial program load. Use OPTIONS described below or ",
51 "provide the name of a SECTION defined in the zIPL configuration file.",
52 "",
53 "-h, --help Print this help, then exit",
54 "-v, --version Print version information, then exit",
55 "-c, --config CONFIGFILE Read configuration from CONFIGFILE",
56 "-t, --target TARGETDIR Write bootmap file to TARGETDIR and install",
57 " bootloader on device containing TARGETDIR",
58 " --targetbase BASEDEVICE Install bootloader on BASEDEVICE",
59 " --targettype TYPE Use device type: CDL, LDL, FBA, SCSI",
60 " --targetgeometry C,H,S Use disk geometry: cylinders,heads,sectors",
61 " --targetblocksize SIZE Use number of bytes per block",
62 " --targetoffset OFFSET Use offset between logical and physical disk",
63 "-i, --image IMAGEFILE[,ADDR] Install Linux kernel image from IMAGEFILE",
64 "-r, --ramdisk RAMDISK[,ADDR] Install initial ramdisk from file RAMDISK",
65 "-p, --parmfile PARMFILE[,ADDR] Use kernel parmline stored in PARMFILE",
66 "-P, --parameters PARMLINE Use specified kernel PARMLINE",
67 "-T, --tape TAPEDEV Install bootloader on tape device TAPEDEV",
68 "-s, --segment SEGMENT,ADDR Install a segment from file SEGMENT",
69 "-d, --dumpto DUMPDEV[,SIZE] Install a system dump record on tape device",
70 " or disk partition DUMPDEV",
71 "-M, --mvdump DEVLIST[,SIZE] Install a multi-volume dump record on each",
72 " disk partition listed in file DEVLIST",
73 "-f, --force Disable sanity check while producing a",
74 " multi-volume dump",
75 "-D, --dumptofs DUMPDEV[,SIZE] Install a system dump record for dumping to",
76 " filesystem on partition identified by DUMPDEV",
77 "-m, --menu MENU Install multi-boot configuration MENU",
78 "-n, --noninteractive Answer all confirmation questions with 'yes'",
79 "-V, --verbose Provide more verbose output",
80 "-a, --add-files Add all referenced files to bootmap file",
81 " --dry-run Simulate run but don't modify IPL records"
85 /* Print usage information. */
86 static void
87 print_usage(void)
89 unsigned int i;
91 for (i=0; i < sizeof(usage_text) / sizeof(usage_text[0]); i++)
92 printf("%s\n", usage_text[i]);
96 /* Print version information. */
97 static void
98 print_version(void)
100 printf("%s version %s\n", tool_name, RELEASE_STRING);
101 printf("%s\n", copyright_notice);
105 /* Check whether calling user is root. Return 0 if user is root, non-zero
106 * otherwise. */
107 static int
108 check_for_root(void)
110 if (geteuid() != 0) {
111 error_clear_text();
112 error_reason("Must be root to perform this operation");
113 return -1;
114 } else
115 return 0;
120 main(int argc, char* argv[])
122 struct disk_info* info;
123 disk_blockptr_t program_table;
124 disk_blockptr_t* stage2_list;
125 blocknum_t stage2_count;
126 struct job_data* job;
127 char* device;
128 int rc;
130 /* Check internals */
131 rc = boot_check_data();
132 if (rc) {
133 error_text("Internal error");
134 error_print();
135 return 1;
137 /* Find out what we're supposed to do */
138 rc = job_get(argc, argv, &job);
139 if (rc) {
140 error_print();
141 return 1;
143 /* Check for priority options --help and --version */
144 if (job->id == job_print_usage) {
145 print_usage();
146 return 0;
147 } else if (job->id == job_print_version) {
148 print_version();
149 return 0;
151 /* Make sure we're running as root */
152 if (check_for_root()) {
153 job_free(job);
154 error_print();
155 return 1;
157 /* Set global option variables */
158 verbose = job->verbose;
159 interactive = !job->noninteractive;
160 dry_run = job->dry_run;
161 if (dry_run)
162 printf("Starting dry-run, target device contents will NOT be "
163 "modified\n");
164 /* Make sure new files are only user-accessible */
165 umask(077);
166 /* Do it */
167 switch (job->id) {
168 case job_ipl:
169 case job_segment:
170 case job_dump_fs:
171 case job_menu:
172 /* Create bootmap */
173 stage2_list = NULL;
174 rc = bootmap_create(job, &program_table, &stage2_list,
175 &stage2_count, &device, &info);
176 if (rc)
177 break;
178 /* Install boot loader */
179 rc = install_bootloader(device, &program_table,
180 stage2_list, stage2_count, info, job);
181 if (stage2_list != NULL)
182 free(stage2_list);
183 misc_free_temp_dev(device);
184 disk_free_info(info);
185 break;
186 case job_ipl_tape:
187 rc = install_tapeloader(job->data.ipl_tape.device,
188 job->data.ipl_tape.image,
189 job->data.ipl_tape.parmline,
190 job->data.ipl_tape.ramdisk,
191 job->data.ipl_tape.image_addr,
192 job->data.ipl_tape.parm_addr,
193 job->data.ipl_tape.ramdisk_addr);
194 break;
195 case job_dump_partition:
196 /* Retrieve target device information */
197 rc = install_dump(job->data.dump.device, &job->target,
198 job->data.dump.mem);
199 break;
200 case job_mvdump:
201 rc = install_mvdump(job->data.mvdump.device,
202 &job->target,
203 job->data.mvdump.device_count,
204 job->data.mvdump.mem,
205 job->data.mvdump.force);
206 break;
207 case job_print_usage:
208 case job_print_version:
209 /* Should not happen */
210 break;
212 switch (rc) {
213 case 0: /* Operation completed successfully */
214 if (verbose)
215 printf("Syncing disks...\n");
216 if (!dry_run)
217 sync();
218 printf("Done.\n");
219 break;
220 case -2: /* Operation canceled by user */
221 break;
222 default: /* An error occurred */
223 error_print();
224 break;
226 job_free(job);
227 return abs(rc);