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