xref: /minix3/sys/arch/i386/stand/lib/bootinfo_biosgeom.c (revision 58a2b0008e28f606a7f7f5faaeaba4faac57a1ea)
1*58a2b000SEvgeniy Ivanov /*	$NetBSD: bootinfo_biosgeom.c,v 1.21 2010/12/25 01:19:33 jakllsch Exp $	*/
2*58a2b000SEvgeniy Ivanov 
3*58a2b000SEvgeniy Ivanov /*
4*58a2b000SEvgeniy Ivanov  * Copyright (c) 1997
5*58a2b000SEvgeniy Ivanov  *	Matthias Drochner.  All rights reserved.
6*58a2b000SEvgeniy Ivanov  *
7*58a2b000SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
8*58a2b000SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
9*58a2b000SEvgeniy Ivanov  * are met:
10*58a2b000SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
11*58a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
12*58a2b000SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
13*58a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
14*58a2b000SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
15*58a2b000SEvgeniy Ivanov  *
16*58a2b000SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*58a2b000SEvgeniy Ivanov  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*58a2b000SEvgeniy Ivanov  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*58a2b000SEvgeniy Ivanov  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*58a2b000SEvgeniy Ivanov  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*58a2b000SEvgeniy Ivanov  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*58a2b000SEvgeniy Ivanov  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*58a2b000SEvgeniy Ivanov  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*58a2b000SEvgeniy Ivanov  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*58a2b000SEvgeniy Ivanov  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*58a2b000SEvgeniy Ivanov  *
27*58a2b000SEvgeniy Ivanov  */
28*58a2b000SEvgeniy Ivanov 
29*58a2b000SEvgeniy Ivanov #include <sys/types.h>
30*58a2b000SEvgeniy Ivanov #include <machine/disklabel.h>
31*58a2b000SEvgeniy Ivanov #include <machine/cpu.h>
32*58a2b000SEvgeniy Ivanov 
33*58a2b000SEvgeniy Ivanov #include <lib/libkern/libkern.h>
34*58a2b000SEvgeniy Ivanov #include <lib/libsa/stand.h>
35*58a2b000SEvgeniy Ivanov 
36*58a2b000SEvgeniy Ivanov #include "libi386.h"
37*58a2b000SEvgeniy Ivanov #include "biosdisk_ll.h"
38*58a2b000SEvgeniy Ivanov #include "bootinfo.h"
39*58a2b000SEvgeniy Ivanov 
40*58a2b000SEvgeniy Ivanov #ifdef BIOSDISK_EXTINFO_V3
41*58a2b000SEvgeniy Ivanov static struct {
42*58a2b000SEvgeniy Ivanov 	char	*name;
43*58a2b000SEvgeniy Ivanov 	int	flag;
44*58a2b000SEvgeniy Ivanov } bus_names[] = { {"ISA", BI_GEOM_BUS_ISA},
45*58a2b000SEvgeniy Ivanov 		  {"PCI", BI_GEOM_BUS_PCI},
46*58a2b000SEvgeniy Ivanov 		  {NULL, BI_GEOM_BUS_OTHER} };
47*58a2b000SEvgeniy Ivanov static struct {
48*58a2b000SEvgeniy Ivanov 	char	*name;
49*58a2b000SEvgeniy Ivanov 	int	flag;
50*58a2b000SEvgeniy Ivanov } iface_names[] = { {"ATA", BI_GEOM_IFACE_ATA},
51*58a2b000SEvgeniy Ivanov 		    {"ATAPI", BI_GEOM_IFACE_ATAPI},
52*58a2b000SEvgeniy Ivanov 		    {"SCSI", BI_GEOM_IFACE_SCSI},
53*58a2b000SEvgeniy Ivanov 		    {"USB", BI_GEOM_IFACE_USB},
54*58a2b000SEvgeniy Ivanov 		    {"1394", BI_GEOM_IFACE_1394},
55*58a2b000SEvgeniy Ivanov 		    {"FIBRE", BI_GEOM_IFACE_FIBRE},
56*58a2b000SEvgeniy Ivanov 		    {NULL, BI_GEOM_IFACE_OTHER} };
57*58a2b000SEvgeniy Ivanov #endif
58*58a2b000SEvgeniy Ivanov 
59*58a2b000SEvgeniy Ivanov void
60*58a2b000SEvgeniy Ivanov bi_getbiosgeom(void)
61*58a2b000SEvgeniy Ivanov {
62*58a2b000SEvgeniy Ivanov 	struct btinfo_biosgeom *bibg;
63*58a2b000SEvgeniy Ivanov 	int i, j, nvalid;
64*58a2b000SEvgeniy Ivanov 	int nhd;
65*58a2b000SEvgeniy Ivanov 	unsigned int cksum;
66*58a2b000SEvgeniy Ivanov 	struct biosdisk_ll d;
67*58a2b000SEvgeniy Ivanov 	struct biosdisk_extinfo ed;
68*58a2b000SEvgeniy Ivanov 	char buf[BIOSDISK_DEFAULT_SECSIZE];
69*58a2b000SEvgeniy Ivanov 
70*58a2b000SEvgeniy Ivanov 	nhd = get_harddrives();
71*58a2b000SEvgeniy Ivanov #ifdef GEOM_DEBUG
72*58a2b000SEvgeniy Ivanov 	printf("nhd %d\n", nhd);
73*58a2b000SEvgeniy Ivanov #endif
74*58a2b000SEvgeniy Ivanov 
75*58a2b000SEvgeniy Ivanov 	bibg = alloc(sizeof(struct btinfo_biosgeom)
76*58a2b000SEvgeniy Ivanov 		     + (nhd - 1) * sizeof(struct bi_biosgeom_entry));
77*58a2b000SEvgeniy Ivanov 	if (bibg == NULL)
78*58a2b000SEvgeniy Ivanov 		return;
79*58a2b000SEvgeniy Ivanov 
80*58a2b000SEvgeniy Ivanov 	for (i = nvalid = 0; i < MAX_BIOSDISKS && nvalid < nhd; i++) {
81*58a2b000SEvgeniy Ivanov 
82*58a2b000SEvgeniy Ivanov 		d.dev = 0x80 + i;
83*58a2b000SEvgeniy Ivanov 
84*58a2b000SEvgeniy Ivanov 		if (set_geometry(&d, &ed))
85*58a2b000SEvgeniy Ivanov 			continue;
86*58a2b000SEvgeniy Ivanov 		memset(&bibg->disk[nvalid], 0, sizeof(bibg->disk[nvalid]));
87*58a2b000SEvgeniy Ivanov 
88*58a2b000SEvgeniy Ivanov 		bibg->disk[nvalid].sec = d.sec;
89*58a2b000SEvgeniy Ivanov 		bibg->disk[nvalid].head = d.head;
90*58a2b000SEvgeniy Ivanov 		bibg->disk[nvalid].cyl = d.cyl;
91*58a2b000SEvgeniy Ivanov 		bibg->disk[nvalid].dev = d.dev;
92*58a2b000SEvgeniy Ivanov 
93*58a2b000SEvgeniy Ivanov 		if (readsects(&d, 0, 1, buf, 0)) {
94*58a2b000SEvgeniy Ivanov 			bibg->disk[nvalid].flags |= BI_GEOM_INVALID;
95*58a2b000SEvgeniy Ivanov 			nvalid++;
96*58a2b000SEvgeniy Ivanov 			continue;
97*58a2b000SEvgeniy Ivanov 		}
98*58a2b000SEvgeniy Ivanov 
99*58a2b000SEvgeniy Ivanov #ifdef GEOM_DEBUG
100*58a2b000SEvgeniy Ivanov 		printf("#%d: %x: C %d H %d S %d\n", nvalid,
101*58a2b000SEvgeniy Ivanov 		       d.dev, d.cyl, d.head, d.sec);
102*58a2b000SEvgeniy Ivanov 		printf("   sz %d fl %x cyl %d head %d sec %d totsec %"PRId64" sbytes %d\n",
103*58a2b000SEvgeniy Ivanov 		       ed.size, ed.flags, ed.cyl, ed.head, ed.sec,
104*58a2b000SEvgeniy Ivanov 		       ed.totsec, ed.sbytes);
105*58a2b000SEvgeniy Ivanov #endif
106*58a2b000SEvgeniy Ivanov 
107*58a2b000SEvgeniy Ivanov 		if (d.flags & BIOSDISK_INT13EXT) {
108*58a2b000SEvgeniy Ivanov 			bibg->disk[nvalid].totsec = ed.totsec;
109*58a2b000SEvgeniy Ivanov 			bibg->disk[nvalid].flags |= BI_GEOM_EXTINT13;
110*58a2b000SEvgeniy Ivanov 		}
111*58a2b000SEvgeniy Ivanov #ifdef BIOSDISK_EXTINFO_V3
112*58a2b000SEvgeniy Ivanov #ifdef GEOM_DEBUG
113*58a2b000SEvgeniy Ivanov 		printf("   edd_cfg %x, sig %x, len %x, bus %s type %s\n",
114*58a2b000SEvgeniy Ivanov 		       ed.edd_cfg, ed.devpath_sig, ed.devpath_len,
115*58a2b000SEvgeniy Ivanov 		       ed.host_bus, ed.iface_type);
116*58a2b000SEvgeniy Ivanov #endif
117*58a2b000SEvgeniy Ivanov 
118*58a2b000SEvgeniy Ivanov 		/* The v3.0 stuff will help identify the disks */
119*58a2b000SEvgeniy Ivanov 		if (ed.size >= offsetof(struct biosdisk_ext13info, checksum)
120*58a2b000SEvgeniy Ivanov 		    && ed.devpath_sig == EXTINFO_DEVPATH_SIGNATURE) {
121*58a2b000SEvgeniy Ivanov 			char *cp;
122*58a2b000SEvgeniy Ivanov 
123*58a2b000SEvgeniy Ivanov 			for (cp = (void *)&ed.devpath_sig, cksum = 0;
124*58a2b000SEvgeniy Ivanov 			     cp <= (char *)&ed.checksum; cp++) {
125*58a2b000SEvgeniy Ivanov 				cksum += *cp;
126*58a2b000SEvgeniy Ivanov 			}
127*58a2b000SEvgeniy Ivanov 			if ((cksum & 0xff) != 0)
128*58a2b000SEvgeniy Ivanov 				bibg->disk[nvalid].flags |= BI_GEOM_BADCKSUM;
129*58a2b000SEvgeniy Ivanov #ifdef GEOM_DEBUG
130*58a2b000SEvgeniy Ivanov 			printf("checksum %x\n", cksum & 0xff);
131*58a2b000SEvgeniy Ivanov #endif
132*58a2b000SEvgeniy Ivanov 			for (j = 0; ; j++) {
133*58a2b000SEvgeniy Ivanov 				cp = bus_names[j].name;
134*58a2b000SEvgeniy Ivanov 				if (cp == NULL)
135*58a2b000SEvgeniy Ivanov 					break;
136*58a2b000SEvgeniy Ivanov 				if (strncmp(cp, ed.host_bus,
137*58a2b000SEvgeniy Ivanov 					    sizeof(ed.host_bus)) == 0)
138*58a2b000SEvgeniy Ivanov 					break;
139*58a2b000SEvgeniy Ivanov 			}
140*58a2b000SEvgeniy Ivanov #ifdef GEOM_DEBUG
141*58a2b000SEvgeniy Ivanov 			printf("bus %s (%x)\n", cp ? cp : "null",
142*58a2b000SEvgeniy Ivanov 			       bus_names[j].flag);
143*58a2b000SEvgeniy Ivanov #endif
144*58a2b000SEvgeniy Ivanov 			bibg->disk[nvalid].flags |= bus_names[j].flag;
145*58a2b000SEvgeniy Ivanov 			for (j = 0; ; j++) {
146*58a2b000SEvgeniy Ivanov 				cp = iface_names[j].name;
147*58a2b000SEvgeniy Ivanov 				if (cp == NULL)
148*58a2b000SEvgeniy Ivanov 					break;
149*58a2b000SEvgeniy Ivanov 				if (strncmp(cp, ed.iface_type,
150*58a2b000SEvgeniy Ivanov 					    sizeof(ed.iface_type)) == 0)
151*58a2b000SEvgeniy Ivanov 					break;
152*58a2b000SEvgeniy Ivanov 			}
153*58a2b000SEvgeniy Ivanov 			bibg->disk[nvalid].flags |= iface_names[j].flag;
154*58a2b000SEvgeniy Ivanov 			/* Dump raw interface path and device path */
155*58a2b000SEvgeniy Ivanov 			bibg->disk[nvalid].interface_path =
156*58a2b000SEvgeniy Ivanov 					ed.interface_path.ip_32[0];
157*58a2b000SEvgeniy Ivanov 			bibg->disk[nvalid].device_path =
158*58a2b000SEvgeniy Ivanov 					ed.device_path.dp_64[0];
159*58a2b000SEvgeniy Ivanov #ifdef GEOM_DEBUG
160*58a2b000SEvgeniy Ivanov 			printf("device %s (%x) interface %x path %llx\n",
161*58a2b000SEvgeniy Ivanov 			       cp ? cp : "null",
162*58a2b000SEvgeniy Ivanov 			       iface_names[j].flag,
163*58a2b000SEvgeniy Ivanov 			       ed.interface_path.ip_32[0],
164*58a2b000SEvgeniy Ivanov 			       ed.device_path.dp_64[0]);
165*58a2b000SEvgeniy Ivanov #endif
166*58a2b000SEvgeniy Ivanov 		}
167*58a2b000SEvgeniy Ivanov #endif
168*58a2b000SEvgeniy Ivanov 
169*58a2b000SEvgeniy Ivanov 		for (j = 0, cksum = 0; j < BIOSDISK_DEFAULT_SECSIZE; j++)
170*58a2b000SEvgeniy Ivanov 			cksum += buf[j];
171*58a2b000SEvgeniy Ivanov 		bibg->disk[nvalid].cksum = cksum;
172*58a2b000SEvgeniy Ivanov 		memcpy(bibg->disk[nvalid].dosparts, &buf[MBR_PART_OFFSET],
173*58a2b000SEvgeniy Ivanov 		       sizeof(bibg->disk[nvalid].dosparts));
174*58a2b000SEvgeniy Ivanov 		nvalid++;
175*58a2b000SEvgeniy Ivanov 	}
176*58a2b000SEvgeniy Ivanov 
177*58a2b000SEvgeniy Ivanov 	bibg->num = nvalid;
178*58a2b000SEvgeniy Ivanov 
179*58a2b000SEvgeniy Ivanov 	BI_ADD(bibg, BTINFO_BIOSGEOM, sizeof(struct btinfo_biosgeom)
180*58a2b000SEvgeniy Ivanov 	       + nvalid * sizeof(struct bi_biosgeom_entry));
181*58a2b000SEvgeniy Ivanov }
182