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