inst.c revision 1.11 1 /* $NetBSD: inst.c,v 1.11 2003/11/14 16:52:40 tsutsui Exp $ */
2
3 /*-
4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Portions of this program are inspired by (and have borrowed code from)
41 * the `editlabel' program that accompanies NetBSD/vax, which carries
42 * the following notice:
43 *
44 * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
45 * All rights reserved.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed at Ludd, University of
58 * Lule}, Sweden and its contributors.
59 * 4. The name of the author may not be used to endorse or promote products
60 * derived from this software without specific prior written permission
61 *
62 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
63 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
64 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
65 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
66 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
67 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
68 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
69 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
70 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * SUCH DAMAGE.
73 */
74
75 #define DKTYPENAMES
76
77 #include <sys/param.h>
78 #include <sys/reboot.h>
79 #include <sys/disklabel.h>
80
81 #include <lib/libsa/stand.h>
82 #include <lib/libkern/libkern.h>
83
84 #include <hp300/stand/common/samachdep.h>
85
86 char line[100];
87
88 extern u_int opendev;
89 extern char *lowram;
90 extern int noconsole;
91 extern int netio_ask;
92
93 char *kernel_name = "/netbsd";
94
95 void main(void);
96 void dsklabel(void);
97 void miniroot(void);
98 void bootmini(void);
99 void resetsys(void);
100 void gethelp(void);
101 int opendisk(char *, char *, int, char, int *);
102 void disklabel_edit(struct disklabel *);
103 void disklabel_show(struct disklabel *);
104 int disklabel_write(char *, int, struct open_file *);
105 void get_fstype(struct disklabel *lp, int);
106 int a2int(char *);
107
108 struct inst_command {
109 char *ic_cmd; /* command name */
110 char *ic_desc; /* command description */
111 void (*ic_func) __P((void)); /* handling function */
112 } inst_commands[] = {
113 { "disklabel", "place partition map on disk", dsklabel },
114 { "miniroot", "place miniroot on disk", miniroot },
115 { "boot", "boot from miniroot", bootmini },
116 { "reset", "reset the system", resetsys },
117 { "help", "display command list", gethelp },
118 };
119 #define NCMDS (sizeof(inst_commands) / sizeof(inst_commands[0]))
120
121 void
122 main()
123 {
124 int i;
125
126 /*
127 * We want netopen() to ask for IP address, etc, rather
128 * that using bootparams.
129 */
130 netio_ask = 1;
131
132 printf("\n");
133 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
134 printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
135 printf(">> HP 9000/%s SPU\n", getmachineid());
136 gethelp();
137
138 for (;;) {
139 printf("sys_inst> ");
140 memset(line, 0, sizeof(line));
141 gets(line);
142 if (line[0] == '\n' || line[0] == '\0')
143 continue;
144
145 for (i = 0; i < NCMDS; ++i)
146 if (strcmp(line, inst_commands[i].ic_cmd) == 0) {
147 (*inst_commands[i].ic_func)();
148 break;
149 }
150
151
152 if (i == NCMDS)
153 printf("unknown command: %s\n", line);
154 }
155 }
156
157 void
158 gethelp()
159 {
160 int i;
161
162 printf(">> Available commands:\n");
163 for (i = 0; i < NCMDS; ++i)
164 printf(">> %s - %s\n", inst_commands[i].ic_cmd,
165 inst_commands[i].ic_desc);
166 }
167
168 /*
169 * Do all the steps necessary to place a disklabel on a disk.
170 * Note, this assumes 512 byte sectors.
171 */
172 void
173 dsklabel()
174 {
175 struct disklabel *lp;
176 struct open_file *disk_ofp;
177 int dfd, error;
178 size_t xfersize;
179 char block[DEV_BSIZE], diskname[64];
180 extern struct open_file files[];
181
182 printf(
183 "You will be asked several questions about your disk, most of which\n"
184 "require prior knowledge of the disk's geometry. There is no easy way\n"
185 "for the system to provide this information for you. If you do not have\n"
186 "this information, please consult your disk's manual or another\n"
187 "informative source.\n\n");
188
189 /* Error message printed by opendisk() */
190 if (opendisk("Disk to label?", diskname, sizeof(diskname),
191 ('a' + RAW_PART), &dfd))
192 return;
193
194 disk_ofp = &files[dfd];
195
196 memset(block, 0, sizeof(block));
197 if ((error = (*disk_ofp->f_dev->dv_strategy)(disk_ofp->f_devdata,
198 F_READ, LABELSECTOR, sizeof(block), block, &xfersize)) != 0) {
199 printf("cannot read disk %s, errno = %d\n", diskname, error);
200 return;
201 }
202
203 printf("Successfully read %d bytes from %s\n", xfersize, diskname);
204
205 lp = (struct disklabel *)((void *)(&block[LABELOFFSET]));
206
207 disklabel_loop:
208 memset(line, 0, sizeof(line));
209 printf("(z)ap, (e)dit, (s)how, (w)rite, (d)one > ");
210 gets(line);
211 if (line[0] == '\n' || line[0] == '\0')
212 goto disklabel_loop;
213
214 switch (line[0]) {
215 case 'z':
216 case 'Z': {
217 char zap[DEV_BSIZE];
218 memset(zap, 0, sizeof(zap));
219 (void)(*disk_ofp->f_dev->dv_strategy)(disk_ofp->f_devdata,
220 F_WRITE, LABELSECTOR, sizeof(zap), zap, &xfersize);
221 }
222 goto out;
223 /* NOTREACHED */
224
225 case 'e':
226 case 'E':
227 disklabel_edit(lp);
228 break;
229
230 case 's':
231 case 'S':
232 disklabel_show(lp);
233 break;
234
235 case 'w':
236 case 'W':
237 /*
238 * Error message will be displayed by disklabel_write()
239 */
240 if (disklabel_write(block, sizeof(block), disk_ofp))
241 goto out;
242 else
243 printf("Successfully wrote label to %s\n", diskname);
244 break;
245
246 case 'd':
247 case 'D':
248 goto out;
249 /* NOTREACHED */
250
251 default:
252 printf("unknown command: %s\n", line);
253 }
254
255 goto disklabel_loop;
256 /* NOTREACHED */
257
258 out:
259 /*
260 * Close disk. Marks disk `not alive' so that partition
261 * information will be reloaded upon next open.
262 */
263 (void)close(dfd);
264 }
265
266 #define GETNUM(out, num) \
267 printf((out), (num)); \
268 memset(line, 0, sizeof(line)); \
269 gets(line); \
270 if (line[0]) \
271 (num) = atoi(line);
272
273 #define GETNUM2(out, num1, num2) \
274 printf((out), (num1), (num2)); \
275 memset(line, 0, sizeof(line)); \
276 gets(line); \
277 if (line[0]) \
278 (num2) = atoi(line);
279
280 #define GETSTR(out, str) \
281 printf((out), (str)); \
282 memset(line, 0, sizeof(line)); \
283 gets(line); \
284 if (line[0]) \
285 strcpy((str), line);
286
287 #define FLAGS(out, flag) \
288 printf((out), lp->d_flags & (flag) ? 'y' : 'n'); \
289 memset(line, 0, sizeof(line)); \
290 gets(line); \
291 if (line[0] == 'y' || line[0] == 'Y') \
292 lp->d_flags |= (flag); \
293 else \
294 lp->d_flags &= ~(flag);
295
296 struct fsname_to_type {
297 const char *name;
298 u_int8_t type;
299 } n_to_t[] = {
300 { "unused", FS_UNUSED },
301 { "ffs", FS_BSDFFS },
302 { "swap", FS_SWAP },
303 { "boot", FS_BOOT },
304 { NULL, 0 },
305 };
306
307 void
308 get_fstype(lp, partno)
309 struct disklabel *lp;
310 int partno;
311 {
312 static int blocksize = 8192; /* XXX */
313 struct partition *pp = &lp->d_partitions[partno];
314 struct fsname_to_type *np;
315 int fragsize;
316 char line[80], str[80];
317
318 if (pp->p_size == 0) {
319 /*
320 * No need to bother asking for a zero-sized partition.
321 */
322 pp->p_fstype = FS_UNUSED;
323 return;
324 }
325
326 /*
327 * Select a default.
328 * XXX Should we check what might be in the label already?
329 */
330 if (partno == 1)
331 strcpy(str, "swap");
332 else if (partno == RAW_PART)
333 strcpy(str, "boot");
334 else
335 strcpy(str, "ffs");
336
337 again:
338 GETSTR(" fstype? [%s] ", str);
339
340 for (np = n_to_t; np->name != NULL; np++)
341 if (strcmp(str, np->name) == 0)
342 break;
343
344 if (np->name == NULL) {
345 printf("Please use one of: ");
346 for (np = n_to_t; np->name != NULL; np++)
347 printf(" %s", np->name);
348 printf(".\n");
349 goto again;
350 }
351
352 pp->p_fstype = np->type;
353
354 if (pp->p_fstype != FS_BSDFFS)
355 return;
356
357 /*
358 * Get additional information needed for FFS.
359 */
360 ffs_again:
361 GETNUM(" FFS block size? [%d] ", blocksize);
362 if (blocksize < NBPG || (blocksize % NBPG) != 0) {
363 printf("FFS block size must be a multiple of %d.\n", NBPG);
364 goto ffs_again;
365 }
366
367 fragsize = blocksize / 8; /* XXX */
368 fragsize = max(fragsize, lp->d_secsize);
369 GETNUM(" FFS fragment size? [%d] ", fragsize);
370 if (fragsize < lp->d_secsize || (fragsize % lp->d_secsize) != 0) {
371 printf("FFS fragment size must be a multiple of sector size"
372 " (%d).\n", lp->d_secsize);
373 goto ffs_again;
374 }
375 if ((blocksize % fragsize) != 0) {
376 printf("FFS fragment size must be an even divisor of FFS"
377 " block size (%d).\n", blocksize);
378 goto ffs_again;
379 }
380
381 /*
382 * XXX Better sanity checking?
383 */
384
385 pp->p_frag = blocksize / fragsize;
386 pp->p_fsize = fragsize;
387 }
388
389 void
390 disklabel_edit(lp)
391 struct disklabel *lp;
392 {
393 int i;
394
395 printf("Select disk type. Valid types:\n");
396 for (i = 0; i < DKMAXTYPES; i++)
397 printf("%d %s\n", i, dktypenames[i]);
398 printf("\n");
399
400 GETNUM("Disk type (number)? [%d] ", lp->d_type);
401 GETSTR("Disk model name? [%s] ", lp->d_typename);
402 GETSTR("Disk pack name? [%s] ", lp->d_packname);
403 FLAGS("Bad sectoring? [%c] ", D_BADSECT);
404 FLAGS("Ecc? [%c] ", D_ECC);
405 FLAGS("Removable? [%c] ", D_REMOVABLE);
406
407 printf("\n");
408
409 GETNUM("Interleave? [%d] ", lp->d_interleave);
410 GETNUM("Rpm? [%d] ", lp->d_rpm);
411 GETNUM("Trackskew? [%d] ", lp->d_trackskew);
412 GETNUM("Cylinderskew? [%d] ", lp->d_cylskew);
413 GETNUM("Headswitch? [%d] ", lp->d_headswitch);
414 GETNUM("Track-to-track? [%d] ", lp->d_trkseek);
415 GETNUM("Drivedata 0? [%d] ", lp->d_drivedata[0]);
416 GETNUM("Drivedata 1? [%d] ", lp->d_drivedata[1]);
417 GETNUM("Drivedata 2? [%d] ", lp->d_drivedata[2]);
418 GETNUM("Drivedata 3? [%d] ", lp->d_drivedata[3]);
419 GETNUM("Drivedata 4? [%d] ", lp->d_drivedata[4]);
420
421 printf("\n");
422
423 GETNUM("Bytes/sector? [%d] ", lp->d_secsize);
424 GETNUM("Sectors/track? [%d] ", lp->d_nsectors);
425 GETNUM("Tracks/cylinder? [%d] ", lp->d_ntracks);
426 if (lp->d_secpercyl == 0)
427 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
428 GETNUM("Sectors/cylinder? [%d] ", lp->d_secpercyl);
429 GETNUM("Cylinders? [%d] ", lp->d_ncylinders);
430 if (lp->d_secperunit == 0)
431 lp->d_secperunit = lp->d_ncylinders * lp->d_secpercyl;
432 GETNUM("Total sectors? [%d] ", lp->d_secperunit);
433
434 printf(
435 "Enter partition table. Note, sizes and offsets are in sectors.\n\n");
436
437 lp->d_npartitions = MAXPARTITIONS;
438 for (i = 0; i < lp->d_npartitions; ++i) {
439 GETNUM2("%c partition: offset? [%d] ", ('a' + i),
440 lp->d_partitions[i].p_offset);
441 GETNUM(" size? [%d] ", lp->d_partitions[i].p_size);
442 get_fstype(lp, i);
443 }
444
445 /* Perform magic. */
446 lp->d_magic = lp->d_magic2 = DISKMAGIC;
447
448 /* Calculate disklabel checksum. */
449 lp->d_checksum = 0;
450 lp->d_checksum = dkcksum(lp);
451 }
452
453 void
454 disklabel_show(lp)
455 struct disklabel *lp;
456 {
457 int i;
458 struct partition *pp;
459
460 /*
461 * Check for valid disklabel.
462 */
463 if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC) {
464 printf("No disklabel to show.\n");
465 return;
466 }
467
468 if (lp->d_npartitions > MAXPARTITIONS || dkcksum(lp) != 0) {
469 printf("Corrupted disklabel.\n");
470 return;
471 }
472
473 printf("\ndisk type %d (%s), %s: %s%s%s\n", lp->d_type,
474 lp->d_type < DKMAXTYPES ? dktypenames[lp->d_type] :
475 dktypenames[0], lp->d_typename,
476 (lp->d_flags & D_REMOVABLE) ? " removable" : "",
477 (lp->d_flags & D_ECC) ? " ecc" : "",
478 (lp->d_flags & D_BADSECT) ? " badsect" : "");
479
480 printf("interleave %d, rpm %d, trackskew %d, cylinderskew %d\n",
481 lp->d_interleave, lp->d_rpm, lp->d_trackskew, lp->d_cylskew);
482
483 printf("headswitch %d, track-to-track %d, drivedata: %d %d %d %d %d\n",
484 lp->d_headswitch, lp->d_trkseek, lp->d_drivedata[0],
485 lp->d_drivedata[1], lp->d_drivedata[2], lp->d_drivedata[3],
486 lp->d_drivedata[4]);
487
488 printf("\nbytes/sector: %d\n", lp->d_secsize);
489 printf("sectors/track: %d\n", lp->d_nsectors);
490 printf("tracks/cylinder: %d\n", lp->d_ntracks);
491 printf("sectors/cylinder: %d\n", lp->d_secpercyl);
492 printf("cylinders: %d\n", lp->d_ncylinders);
493 printf("total sectors: %d\n", lp->d_secperunit);
494
495 printf("\n%d partitions:\n", lp->d_npartitions);
496 printf(" size offset\n");
497 pp = lp->d_partitions;
498 for (i = 0; i < lp->d_npartitions; i++) {
499 printf("%c: %d, %d\n", 97 + i, lp->d_partitions[i].p_size,
500 lp->d_partitions[i].p_offset);
501 }
502 printf("\n");
503 }
504
505 int
506 disklabel_write(block, len, ofp)
507 char *block;
508 int len;
509 struct open_file *ofp;
510 {
511 int error = 0;
512 size_t xfersize;
513
514 if ((error = (*ofp->f_dev->dv_strategy)(ofp->f_devdata, F_WRITE,
515 LABELSECTOR, len, block, &xfersize)) != 0)
516 printf("cannot write disklabel, errno = %d\n", error);
517
518 return (error);
519 }
520
521 int
522 opendisk(question, diskname, len, partition, fdp)
523 char *question, *diskname;
524 int len;
525 char partition;
526 int *fdp;
527 {
528 char fulldiskname[64];
529 int i;
530
531 getdiskname:
532 printf("%s ", question);
533 memset(diskname, 0, len);
534 memset(fulldiskname, 0, sizeof(fulldiskname));
535 gets(diskname);
536 if (diskname[0] == '\n' || diskname[0] == '\0')
537 goto getdiskname;
538
539 /*
540 * devopen() is picky. Make sure it gets the sort of string it
541 * wants.
542 */
543 memcpy(fulldiskname, diskname,
544 len < sizeof(fulldiskname) ? len : sizeof(fulldiskname));
545 for (i = 0; fulldiskname[i + 1] != '\0'; ++i)
546 /* Nothing. */ ;
547 if (fulldiskname[i] < '0' || fulldiskname[i] > '9') {
548 printf("invalid disk name %s\n", diskname);
549 goto getdiskname;
550 }
551 fulldiskname[++i] = partition; fulldiskname[++i] = ':';
552
553 /*
554 * We always open for writing.
555 */
556 if ((*fdp = open(fulldiskname, 1)) < 0) {
557 printf("cannot open %s\n", diskname);
558 return 1;
559 }
560
561 return 0;
562 }
563
564 /*
565 * Copy a miniroot image from an NFS server or tape to the `b' partition
566 * of the specified disk. Note, this assumes 512 byte sectors.
567 */
568 void
569 miniroot()
570 {
571 int sfd, dfd, i, nblks;
572 char diskname[64], minirootname[128];
573 char block[DEV_BSIZE];
574 char tapename[64];
575 int fileno, ignoreshread, eof, len;
576 struct stat st;
577 size_t xfersize;
578 struct open_file *disk_ofp;
579 extern struct open_file files[];
580
581 /* Error message printed by opendisk() */
582 if (opendisk("Disk for miniroot?", diskname, sizeof(diskname),
583 'b', &dfd))
584 return;
585
586 disk_ofp = &files[dfd];
587
588 getsource:
589 printf("Source? (N)FS, (t)ape, (d)one > ");
590 memset(line, 0, sizeof(line));
591 gets(line);
592 if (line[0] == '\0')
593 goto getsource;
594
595 switch (line[0]) {
596 case 'n':
597 case 'N':
598 name_of_nfs_miniroot:
599 printf("Name of miniroot file? ");
600 memset(line, 0, sizeof(line));
601 memset(minirootname, 0, sizeof(minirootname));
602 gets(line);
603 if (line[0] == '\0')
604 goto name_of_nfs_miniroot;
605 (void)strcat(minirootname, "le0a:");
606 (void)strcat(minirootname, line);
607 if ((sfd = open(minirootname, 0)) < 0) {
608 printf("can't open %s\n", line);
609 return;
610 }
611
612 /*
613 * Find out how big the miniroot is... we can't
614 * check for size because it may be compressed.
615 */
616 ignoreshread = 1;
617 if (fstat(sfd, &st) < 0) {
618 printf("can't stat %s\n", line);
619 goto done;
620 }
621 nblks = (int)(st.st_size / sizeof(block));
622
623 printf("Copying miniroot from %s to %s...", line,
624 diskname);
625 break;
626
627 case 't':
628 case 'T':
629 name_of_tape_miniroot:
630 printf("Which tape device? ");
631 memset(line, 0, sizeof(line));
632 memset(minirootname, 0, sizeof(minirootname));
633 memset(tapename, 0, sizeof(tapename));
634 gets(line);
635 if (line[0] == '\0')
636 goto name_of_tape_miniroot;
637 strcat(minirootname, line);
638 strcat(tapename, line);
639
640 printf("File number (first == 1)? ");
641 memset(line, 0, sizeof(line));
642 gets(line);
643 fileno = a2int(line);
644 if (fileno < 1 || fileno > 8) {
645 printf("Invalid file number: %s\n", line);
646 goto getsource;
647 }
648 for (i = 0; i < sizeof(minirootname); ++i) {
649 if (minirootname[i] == '\0')
650 break;
651 }
652 if (i == sizeof(minirootname) ||
653 (sizeof(minirootname) - i) < 8) {
654 printf("Invalid device name: %s\n", tapename);
655 goto getsource;
656 }
657 minirootname[i++] = 'a' + (fileno - 1);
658 minirootname[i++] = ':';
659 strcat(minirootname, "XXX"); /* lameness in open() */
660
661 ignoreshread = 0;
662 printf("Copy how many %d byte blocks? ", DEV_BSIZE);
663 memset(line, 0, sizeof(line));
664 gets(line);
665 nblks = a2int(line);
666 if (nblks < 0) {
667 printf("Invalid block count: %s\n", line);
668 goto getsource;
669 } else if (nblks == 0) {
670 printf("Zero blocks? Ok, aborting.\n");
671 return;
672 }
673
674 if ((sfd = open(minirootname, 0)) < 0) {
675 printf("can't open %s file %c\n", tapename, fileno);
676 return;
677 }
678
679 printf("Copying %s file %d to %s...", tapename, fileno,
680 diskname);
681 break;
682
683 case 'd':
684 case 'D':
685 return;
686
687 default:
688 printf("Unknown source: %s\n", line);
689 goto getsource;
690 }
691
692 /*
693 * Copy loop...
694 * This is fairly slow... if someone wants to speed it
695 * up, they'll get no complaints from me.
696 */
697 for (i = 0, eof = 0; i < nblks || ignoreshread == 0; i++) {
698 if ((len = read(sfd, block, sizeof(block))) < 0) {
699 printf("Read error, errno = %d\n", errno);
700 goto out;
701 }
702
703 /*
704 * Check for end-of-file.
705 */
706 if (len == 0)
707 goto done;
708 else if (len < sizeof(block))
709 eof = 1;
710
711 if ((*disk_ofp->f_dev->dv_strategy)(disk_ofp->f_devdata,
712 F_WRITE, i, len, block, &xfersize) || xfersize != len) {
713 printf("Bad write at block %d, errno = %d\n",
714 i, errno);
715 goto out;
716 }
717
718 if (eof)
719 goto done;
720 }
721 done:
722 printf("done\n");
723
724 printf("Successfully copied miniroot image.\n");
725
726 out:
727 close(sfd);
728 close(dfd);
729 }
730
731 /*
732 * Boot the kernel from the miniroot image into single-user.
733 */
734 void
735 bootmini()
736 {
737 char diskname[64], bootname[64];
738 int i;
739
740 getdiskname:
741 printf("Disk to boot from? ");
742 memset(diskname, 0, sizeof(diskname));
743 memset(bootname, 0, sizeof(bootname));
744 gets(diskname);
745 if (diskname[0] == '\n' || diskname[0] == '\0')
746 goto getdiskname;
747
748 /*
749 * devopen() is picky. Make sure it gets the sort of string it
750 * wants.
751 */
752 (void)strcat(bootname, diskname);
753 for (i = 0; bootname[i + 1] != '\0'; ++i)
754 /* Nothing. */ ;
755 if (bootname[i] < '0' || bootname[i] > '9') {
756 printf("invalid disk name %s\n", diskname);
757 goto getdiskname;
758 }
759 bootname[++i] = 'b'; bootname[++i] = ':';
760 (void)strcat(bootname, kernel_name);
761
762 howto = RB_SINGLE; /* _Always_ */
763
764 printf("booting: %s -s\n", bootname);
765 exec_hp300(bootname, (u_long)lowram, howto);
766 printf("boot: %s\n", strerror(errno));
767 }
768
769 /*
770 * Reset the system.
771 */
772 void
773 resetsys()
774 {
775
776 call_req_reboot();
777 printf("panic: can't reboot, halting\n");
778 asm("stop #0x2700");
779 }
780
781 /*
782 * XXX Should have a generic atoi for libkern/libsa.
783 */
784 int
785 a2int(cp)
786 char *cp;
787 {
788 int i = 0;
789
790 if (*cp == '\0')
791 return (-1);
792
793 while (*cp != '\0')
794 i = i * 10 + *cp++ - '0';
795 return (i);
796 }
797