]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/geom/geom_apple.c
Disable the EC GPE in the shutdown path. This is correct but is not known
[FreeBSD/FreeBSD.git] / sys / geom / geom_apple.c
1 /*-
2  * Copyright (c) 2002 Peter Grehan.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 /*
28  * GEOM module for Apple Partition Maps
29  *  As described in 'Inside Macintosh Vol 3: About the SCSI Manager -
30  *    The Structure of Block Devices"
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/endian.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/bio.h>
42 #include <sys/lock.h>
43 #include <sys/mutex.h>
44
45 #include <sys/sbuf.h>
46 #include <geom/geom.h>
47 #include <geom/geom_slice.h>
48
49 #define APPLE_CLASS_NAME "APPLE"
50
51 #define NAPMPART  16    /* Max partitions */
52
53 struct apm_partition {
54         char       am_sig[2];
55         u_int32_t  am_mapcnt;
56         u_int32_t  am_start;
57         u_int32_t  am_partcnt;
58         char       am_name[32];
59         char       am_type[32]; 
60 };
61
62 struct g_apple_softc {
63         u_int16_t dd_bsiz;
64         u_int32_t dd_blkcnt;
65         u_int16_t dd_drvrcnt;
66         u_int32_t am_mapcnt0;
67         struct apm_partition apmpart[NAPMPART];
68 };
69
70 static void
71 g_dec_drvrdesc(u_char *ptr, struct g_apple_softc *sc)
72 {
73         sc->dd_bsiz = be16dec(ptr + 2);
74         sc->dd_blkcnt = be32dec(ptr + 4);
75         sc->dd_drvrcnt = be32dec(ptr + 16);
76 }
77
78 static void
79 g_dec_apple_partition(u_char *ptr, struct apm_partition *d)
80 {
81         d->am_sig[0] = ptr[0];
82         d->am_sig[1] = ptr[1];
83         d->am_mapcnt = be32dec(ptr + 4);
84         d->am_start = be32dec(ptr + 8);
85         d->am_partcnt = be32dec(ptr + 12);
86         memcpy(d->am_name, ptr + 16, 32);
87         memcpy(d->am_type, ptr + 48, 32);
88 }
89
90 static int
91 g_apple_start(struct bio *bp)
92 {
93         struct g_provider *pp;
94         struct g_geom *gp;
95         struct g_slicer *gsp;
96
97         pp = bp->bio_to;
98         gp = pp->geom;
99         gsp = gp->softc;
100         if (bp->bio_cmd == BIO_GETATTR) {
101                 if (g_handleattr_off_t(bp, "APM::offset",
102                     gsp->slices[pp->index].offset))
103                         return (1);
104         }
105         return (0);
106 }
107
108 static void
109 g_apple_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, 
110     struct g_consumer *cp __unused, struct g_provider *pp)
111 {
112         struct g_apple_softc *mp;
113         struct g_slicer *gsp;
114
115         gsp = gp->softc;
116         mp = gsp->softc;
117         g_slice_dumpconf(sb, indent, gp, cp, pp);
118         if (pp != NULL) {
119                 if (indent == NULL) {
120                         sbuf_printf(sb, " ty %s",
121                             mp->apmpart[pp->index].am_type);
122                         if (*mp->apmpart[pp->index].am_name)
123                                 sbuf_printf(sb, " sn %s",
124                                     mp->apmpart[pp->index].am_name);
125                 } else {
126                         sbuf_printf(sb, "%s<name>%s</name>\n", indent,
127                             mp->apmpart[pp->index].am_name);
128                         sbuf_printf(sb, "%s<type>%s</type>\n", indent,
129                             mp->apmpart[pp->index].am_type);
130                 }
131         }
132 }
133
134 #if 0
135 static void
136 g_apple_print()
137 {
138
139         /* XXX */
140 }
141 #endif
142
143 static struct g_geom *
144 g_apple_taste(struct g_class *mp, struct g_provider *pp, int insist)
145 {
146         struct g_geom *gp;
147         struct g_consumer *cp;
148         int error, i;
149         struct g_apple_softc *ms;
150         struct apm_partition *apm;
151         u_int sectorsize;
152         u_char *buf;
153
154         g_trace(G_T_TOPOLOGY, "apple_taste(%s,%s)", mp->name, pp->name);
155         g_topology_assert();
156         gp = g_slice_new(mp, NAPMPART, pp, &cp, &ms, sizeof *ms, g_apple_start);
157         if (gp == NULL)
158                 return (NULL);
159         g_topology_unlock();
160         gp->dumpconf = g_apple_dumpconf;
161         do {
162                 if (gp->rank != 2 && insist == 0)
163                         break;
164
165                 sectorsize = cp->provider->sectorsize;
166                 if (sectorsize != 512)
167                         break;
168
169                 buf = g_read_data(cp, 0, sectorsize, &error);
170                 if (buf == NULL || error != 0)
171                         break;
172
173                 /*
174                  * Test for the sector 0 driver record signature, and 
175                  * validate sector and disk size
176                  */
177                 if (buf[0] != 'E' && buf[1] != 'R') {
178                         g_free(buf);
179                         break;
180                 }
181                 g_dec_drvrdesc(buf, ms);
182                 g_free(buf);
183
184                 if (ms->dd_bsiz != 512) {
185                         break;
186                 }
187
188                 /*
189                  * Read in the first partition map
190                  */
191                 buf = g_read_data(cp, sectorsize, sectorsize,  &error);
192                 if (buf == NULL || error != 0)
193                         break;
194
195                 /*
196                  * Decode the first partition: it's another indication of
197                  * validity, as well as giving the size of the partition
198                  * map
199                  */
200                 apm = &ms->apmpart[0];
201                 g_dec_apple_partition(buf, apm);
202                 g_free(buf);
203                 
204                 if (apm->am_sig[0] != 'P' || apm->am_sig[1] != 'M')
205                         break;
206                 ms->am_mapcnt0 = apm->am_mapcnt;
207                
208                 buf = g_read_data(cp, 2 * sectorsize, 
209                     (NAPMPART - 1) * sectorsize,  &error);
210                 if (buf == NULL || error != 0)
211                         break;
212
213                 for (i = 1; i < NAPMPART; i++) {
214                         g_dec_apple_partition(buf + ((i - 1) * sectorsize),
215                             &ms->apmpart[i]);
216                 }
217
218                 for (i = 0; i < NAPMPART; i++) {
219                         apm = &ms->apmpart[i];
220
221                         /*
222                          * Validate partition sig and global mapcount
223                          */
224                         if (apm->am_sig[0] != 'P' ||
225                             apm->am_sig[1] != 'M')
226                                 continue;
227                         if (apm->am_mapcnt != ms->am_mapcnt0)
228                                 continue;
229
230                         if (bootverbose) {
231                                 printf("APM Slice %d (%s/%s) on %s:\n", 
232                                     i + 1, apm->am_name, apm->am_type, 
233                                     gp->name);
234                                 /* g_apple_print(i, dp + i); */
235                         }
236                         g_topology_lock();
237                         g_slice_config(gp, i, G_SLICE_CONFIG_SET,
238                             (off_t)apm->am_start << 9ULL,
239                             (off_t)apm->am_partcnt << 9ULL,
240                             sectorsize,
241                             "%ss%d", gp->name, i + 1);
242                         g_topology_unlock();
243                 }
244                 g_free(buf);
245                 break;
246         } while(0);
247         g_topology_lock();
248         g_access(cp, -1, 0, 0);
249         if (LIST_EMPTY(&gp->provider)) {
250                 g_slice_spoiled(cp);
251                 return (NULL);
252         }
253         return (gp);
254 }
255
256
257 static struct g_class g_apple_class     = {
258         .name = APPLE_CLASS_NAME,
259         .taste = g_apple_taste,
260 };
261
262 DECLARE_GEOM_CLASS(g_apple_class, g_apple);