35 36#include <sys/param.h> 37#include <sys/errno.h> 38#include <sys/endian.h> 39#include <sys/systm.h> 40#include <sys/kernel.h> 41#include <sys/malloc.h> 42#include <sys/bio.h> 43#include <sys/lock.h> 44#include <sys/mutex.h> 45 46#include <sys/diskmbr.h> 47#include <sys/sbuf.h> 48#include <geom/geom.h> 49#include <geom/geom_slice.h> 50 51#define MBR_CLASS_NAME "MBR" 52#define MBREXT_CLASS_NAME "MBREXT" 53 54static struct dos_partition historical_bogus_partition_table[NDOSPART] = { 55 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 56 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 57 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 58 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, }, 59}; 60 61static struct dos_partition historical_bogus_partition_table_fixed[NDOSPART] = { 62 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 63 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 64 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 65 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 254, 255, 255, 0, 50000, }, 66}; 67 68static void 69g_mbr_print(int i, struct dos_partition *dp) 70{ 71 72 printf("[%d] f:%02x typ:%d", i, dp->dp_flag, dp->dp_typ); 73 printf(" s(CHS):%d/%d/%d", DPCYL(dp->dp_scyl, dp->dp_ssect), 74 dp->dp_shd, DPSECT(dp->dp_ssect)); 75 printf(" e(CHS):%d/%d/%d", DPCYL(dp->dp_ecyl, dp->dp_esect), 76 dp->dp_ehd, DPSECT(dp->dp_esect)); 77 printf(" s:%d l:%d\n", dp->dp_start, dp->dp_size); 78} 79 80struct g_mbr_softc { 81 int type [NDOSPART]; 82 u_int sectorsize; 83 u_char sec0[512]; 84}; 85 86static int 87g_mbr_modify(struct g_geom *gp, struct g_mbr_softc *ms, u_char *sec0) 88{ 89 int i, error; 90 off_t l[NDOSPART]; 91 struct dos_partition ndp[NDOSPART], *dp; 92 93 g_topology_assert(); 94 95 if (sec0[0x1fe] != 0x55 && sec0[0x1ff] != 0xaa) 96 return (EBUSY); 97 98 dp = ndp; 99 for (i = 0; i < NDOSPART; i++) { 100 dos_partition_dec( 101 sec0 + DOSPARTOFF + i * sizeof(struct dos_partition), 102 dp + i); 103 if (bootverbose) 104 g_mbr_print(i, dp + i); 105 } 106 if ((!bcmp(dp, historical_bogus_partition_table, 107 sizeof historical_bogus_partition_table)) || 108 (!bcmp(dp, historical_bogus_partition_table_fixed, 109 sizeof historical_bogus_partition_table_fixed))) { 110 /* 111 * We will not allow people to write these from "the inside", 112 * Since properly selfdestructing takes too much code. If 113 * people really want to do this, they cannot have any 114 * providers of this geom open, and in that case they can just 115 * as easily overwrite the MBR in the parent device. 116 */ 117 return(EBUSY); 118 } 119 for (i = 0; i < NDOSPART; i++) { 120 /* 121 * A Protective MBR (PMBR) has a single partition of 122 * type 0xEE spanning the whole disk. Such a MBR 123 * protects a GPT on the disk from MBR tools that 124 * don't know anything about GPT. We're interpreting 125 * it a bit more loosely: any partition of type 0xEE 126 * is to be skipped as it doesn't contain any data 127 * that we should care about. We still allow other 128 * partitions to be present in the MBR. A PMBR will 129 * be handled correctly anyway. 130 */ 131 if (dp[i].dp_typ == DOSPTYP_PMBR) 132 l[i] = 0; 133 else if (dp[i].dp_flag != 0 && dp[i].dp_flag != 0x80) 134 l[i] = 0; 135 else if (dp[i].dp_typ == 0) 136 l[i] = 0; 137 else 138 l[i] = (off_t)dp[i].dp_size * ms->sectorsize; 139 error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK, 140 (off_t)dp[i].dp_start * ms->sectorsize, l[i], 141 ms->sectorsize, "%ss%d", gp->name, 1 + i); 142 if (error) 143 return (error); 144 } 145 for (i = 0; i < NDOSPART; i++) { 146 ms->type[i] = dp[i].dp_typ; 147 g_slice_config(gp, i, G_SLICE_CONFIG_SET, 148 (off_t)dp[i].dp_start * ms->sectorsize, l[i], 149 ms->sectorsize, "%ss%d", gp->name, 1 + i); 150 } 151 bcopy(sec0, ms->sec0, 512); 152 return (0); 153} 154 155static int 156g_mbr_ioctl(struct g_provider *pp, u_long cmd, void *data, struct thread *td) 157{ 158 struct g_geom *gp; 159 struct g_mbr_softc *ms; 160 struct g_slicer *gsp; 161 struct g_consumer *cp; 162 int error; 163 164 gp = pp->geom; 165 gsp = gp->softc; 166 ms = gsp->softc; 167 168 switch(cmd) { 169 case DIOCSMBR: { 170 DROP_GIANT(); 171 g_topology_lock(); 172 /* Validate and modify our slicer instance to match. */ 173 error = g_mbr_modify(gp, ms, data); 174 cp = LIST_FIRST(&gp->consumer); 175 error = g_write_data(cp, 0, data, 512); 176 g_topology_unlock(); 177 PICKUP_GIANT(); 178 return(error); 179 } 180 default: 181 return (ENOIOCTL); 182 } 183} 184 185static int 186g_mbr_start(struct bio *bp) 187{ 188 struct g_provider *pp; 189 struct g_geom *gp; 190 struct g_mbr_softc *mp; 191 struct g_slicer *gsp; 192 int idx; 193 194 pp = bp->bio_to; 195 idx = pp->index; 196 gp = pp->geom; 197 gsp = gp->softc; 198 mp = gsp->softc; 199 if (bp->bio_cmd == BIO_GETATTR) { 200 if (g_handleattr_int(bp, "MBR::type", mp->type[idx])) 201 return (1); 202 if (g_handleattr_off_t(bp, "MBR::offset", 203 gsp->slices[idx].offset)) 204 return (1); 205 } 206 207 return (0); 208} 209 210static void 211g_mbr_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp) 212{ 213 struct g_mbr_softc *mp; 214 struct g_slicer *gsp; 215 216 gsp = gp->softc; 217 mp = gsp->softc; 218 g_slice_dumpconf(sb, indent, gp, cp, pp); 219 if (pp != NULL) { 220 if (indent == NULL) 221 sbuf_printf(sb, " ty %d", mp->type[pp->index]); 222 else 223 sbuf_printf(sb, "%s<type>%d</type>\n", indent, 224 mp->type[pp->index]); 225 } 226} 227 228static struct g_geom * 229g_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist) 230{ 231 struct g_geom *gp; 232 struct g_consumer *cp; 233 int error; 234 struct g_mbr_softc *ms; 235 u_int fwsectors, sectorsize; 236 u_char *buf; 237 238 g_trace(G_T_TOPOLOGY, "mbr_taste(%s,%s)", mp->name, pp->name); 239 g_topology_assert(); 240 gp = g_slice_new(mp, NDOSPART, pp, &cp, &ms, sizeof *ms, g_mbr_start); 241 if (gp == NULL) 242 return (NULL); 243 g_topology_unlock();
| 35 36#include <sys/param.h> 37#include <sys/errno.h> 38#include <sys/endian.h> 39#include <sys/systm.h> 40#include <sys/kernel.h> 41#include <sys/malloc.h> 42#include <sys/bio.h> 43#include <sys/lock.h> 44#include <sys/mutex.h> 45 46#include <sys/diskmbr.h> 47#include <sys/sbuf.h> 48#include <geom/geom.h> 49#include <geom/geom_slice.h> 50 51#define MBR_CLASS_NAME "MBR" 52#define MBREXT_CLASS_NAME "MBREXT" 53 54static struct dos_partition historical_bogus_partition_table[NDOSPART] = { 55 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 56 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 57 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 58 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, }, 59}; 60 61static struct dos_partition historical_bogus_partition_table_fixed[NDOSPART] = { 62 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 63 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 64 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 65 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 254, 255, 255, 0, 50000, }, 66}; 67 68static void 69g_mbr_print(int i, struct dos_partition *dp) 70{ 71 72 printf("[%d] f:%02x typ:%d", i, dp->dp_flag, dp->dp_typ); 73 printf(" s(CHS):%d/%d/%d", DPCYL(dp->dp_scyl, dp->dp_ssect), 74 dp->dp_shd, DPSECT(dp->dp_ssect)); 75 printf(" e(CHS):%d/%d/%d", DPCYL(dp->dp_ecyl, dp->dp_esect), 76 dp->dp_ehd, DPSECT(dp->dp_esect)); 77 printf(" s:%d l:%d\n", dp->dp_start, dp->dp_size); 78} 79 80struct g_mbr_softc { 81 int type [NDOSPART]; 82 u_int sectorsize; 83 u_char sec0[512]; 84}; 85 86static int 87g_mbr_modify(struct g_geom *gp, struct g_mbr_softc *ms, u_char *sec0) 88{ 89 int i, error; 90 off_t l[NDOSPART]; 91 struct dos_partition ndp[NDOSPART], *dp; 92 93 g_topology_assert(); 94 95 if (sec0[0x1fe] != 0x55 && sec0[0x1ff] != 0xaa) 96 return (EBUSY); 97 98 dp = ndp; 99 for (i = 0; i < NDOSPART; i++) { 100 dos_partition_dec( 101 sec0 + DOSPARTOFF + i * sizeof(struct dos_partition), 102 dp + i); 103 if (bootverbose) 104 g_mbr_print(i, dp + i); 105 } 106 if ((!bcmp(dp, historical_bogus_partition_table, 107 sizeof historical_bogus_partition_table)) || 108 (!bcmp(dp, historical_bogus_partition_table_fixed, 109 sizeof historical_bogus_partition_table_fixed))) { 110 /* 111 * We will not allow people to write these from "the inside", 112 * Since properly selfdestructing takes too much code. If 113 * people really want to do this, they cannot have any 114 * providers of this geom open, and in that case they can just 115 * as easily overwrite the MBR in the parent device. 116 */ 117 return(EBUSY); 118 } 119 for (i = 0; i < NDOSPART; i++) { 120 /* 121 * A Protective MBR (PMBR) has a single partition of 122 * type 0xEE spanning the whole disk. Such a MBR 123 * protects a GPT on the disk from MBR tools that 124 * don't know anything about GPT. We're interpreting 125 * it a bit more loosely: any partition of type 0xEE 126 * is to be skipped as it doesn't contain any data 127 * that we should care about. We still allow other 128 * partitions to be present in the MBR. A PMBR will 129 * be handled correctly anyway. 130 */ 131 if (dp[i].dp_typ == DOSPTYP_PMBR) 132 l[i] = 0; 133 else if (dp[i].dp_flag != 0 && dp[i].dp_flag != 0x80) 134 l[i] = 0; 135 else if (dp[i].dp_typ == 0) 136 l[i] = 0; 137 else 138 l[i] = (off_t)dp[i].dp_size * ms->sectorsize; 139 error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK, 140 (off_t)dp[i].dp_start * ms->sectorsize, l[i], 141 ms->sectorsize, "%ss%d", gp->name, 1 + i); 142 if (error) 143 return (error); 144 } 145 for (i = 0; i < NDOSPART; i++) { 146 ms->type[i] = dp[i].dp_typ; 147 g_slice_config(gp, i, G_SLICE_CONFIG_SET, 148 (off_t)dp[i].dp_start * ms->sectorsize, l[i], 149 ms->sectorsize, "%ss%d", gp->name, 1 + i); 150 } 151 bcopy(sec0, ms->sec0, 512); 152 return (0); 153} 154 155static int 156g_mbr_ioctl(struct g_provider *pp, u_long cmd, void *data, struct thread *td) 157{ 158 struct g_geom *gp; 159 struct g_mbr_softc *ms; 160 struct g_slicer *gsp; 161 struct g_consumer *cp; 162 int error; 163 164 gp = pp->geom; 165 gsp = gp->softc; 166 ms = gsp->softc; 167 168 switch(cmd) { 169 case DIOCSMBR: { 170 DROP_GIANT(); 171 g_topology_lock(); 172 /* Validate and modify our slicer instance to match. */ 173 error = g_mbr_modify(gp, ms, data); 174 cp = LIST_FIRST(&gp->consumer); 175 error = g_write_data(cp, 0, data, 512); 176 g_topology_unlock(); 177 PICKUP_GIANT(); 178 return(error); 179 } 180 default: 181 return (ENOIOCTL); 182 } 183} 184 185static int 186g_mbr_start(struct bio *bp) 187{ 188 struct g_provider *pp; 189 struct g_geom *gp; 190 struct g_mbr_softc *mp; 191 struct g_slicer *gsp; 192 int idx; 193 194 pp = bp->bio_to; 195 idx = pp->index; 196 gp = pp->geom; 197 gsp = gp->softc; 198 mp = gsp->softc; 199 if (bp->bio_cmd == BIO_GETATTR) { 200 if (g_handleattr_int(bp, "MBR::type", mp->type[idx])) 201 return (1); 202 if (g_handleattr_off_t(bp, "MBR::offset", 203 gsp->slices[idx].offset)) 204 return (1); 205 } 206 207 return (0); 208} 209 210static void 211g_mbr_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp) 212{ 213 struct g_mbr_softc *mp; 214 struct g_slicer *gsp; 215 216 gsp = gp->softc; 217 mp = gsp->softc; 218 g_slice_dumpconf(sb, indent, gp, cp, pp); 219 if (pp != NULL) { 220 if (indent == NULL) 221 sbuf_printf(sb, " ty %d", mp->type[pp->index]); 222 else 223 sbuf_printf(sb, "%s<type>%d</type>\n", indent, 224 mp->type[pp->index]); 225 } 226} 227 228static struct g_geom * 229g_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist) 230{ 231 struct g_geom *gp; 232 struct g_consumer *cp; 233 int error; 234 struct g_mbr_softc *ms; 235 u_int fwsectors, sectorsize; 236 u_char *buf; 237 238 g_trace(G_T_TOPOLOGY, "mbr_taste(%s,%s)", mp->name, pp->name); 239 g_topology_assert(); 240 gp = g_slice_new(mp, NDOSPART, pp, &cp, &ms, sizeof *ms, g_mbr_start); 241 if (gp == NULL) 242 return (NULL); 243 g_topology_unlock();
|
282}; 283 284DECLARE_GEOM_CLASS(g_mbr_class, g_mbr); 285 286#define NDOSEXTPART 32 287struct g_mbrext_softc { 288 int type [NDOSEXTPART]; 289}; 290 291static int 292g_mbrext_start(struct bio *bp) 293{ 294 struct g_provider *pp; 295 struct g_geom *gp; 296 struct g_mbrext_softc *mp; 297 struct g_slicer *gsp; 298 int idx; 299 300 pp = bp->bio_to; 301 idx = pp->index; 302 gp = pp->geom; 303 gsp = gp->softc; 304 mp = gsp->softc; 305 if (bp->bio_cmd == BIO_GETATTR) { 306 if (g_handleattr_int(bp, "MBR::type", mp->type[idx])) 307 return (1); 308 } 309 return (0); 310} 311 312static void 313g_mbrext_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp) 314{ 315 struct g_mbrext_softc *mp; 316 struct g_slicer *gsp; 317 318 g_slice_dumpconf(sb, indent, gp, cp, pp); 319 gsp = gp->softc; 320 mp = gsp->softc; 321 if (pp != NULL) { 322 if (indent == NULL) 323 sbuf_printf(sb, " ty %d", mp->type[pp->index]); 324 else 325 sbuf_printf(sb, "%s<type>%d</type>\n", indent, 326 mp->type[pp->index]); 327 } 328} 329 330static struct g_geom * 331g_mbrext_taste(struct g_class *mp, struct g_provider *pp, int insist __unused) 332{ 333 struct g_geom *gp; 334 struct g_consumer *cp; 335 int error, i, slice; 336 struct g_mbrext_softc *ms; 337 off_t off; 338 u_char *buf; 339 struct dos_partition dp[4]; 340 u_int fwsectors, sectorsize; 341 342 g_trace(G_T_TOPOLOGY, "g_mbrext_taste(%s,%s)", mp->name, pp->name); 343 g_topology_assert(); 344 if (strcmp(pp->geom->class->name, MBR_CLASS_NAME)) 345 return (NULL); 346 gp = g_slice_new(mp, NDOSEXTPART, pp, &cp, &ms, sizeof *ms, 347 g_mbrext_start); 348 if (gp == NULL) 349 return (NULL); 350 g_topology_unlock();
| 282}; 283 284DECLARE_GEOM_CLASS(g_mbr_class, g_mbr); 285 286#define NDOSEXTPART 32 287struct g_mbrext_softc { 288 int type [NDOSEXTPART]; 289}; 290 291static int 292g_mbrext_start(struct bio *bp) 293{ 294 struct g_provider *pp; 295 struct g_geom *gp; 296 struct g_mbrext_softc *mp; 297 struct g_slicer *gsp; 298 int idx; 299 300 pp = bp->bio_to; 301 idx = pp->index; 302 gp = pp->geom; 303 gsp = gp->softc; 304 mp = gsp->softc; 305 if (bp->bio_cmd == BIO_GETATTR) { 306 if (g_handleattr_int(bp, "MBR::type", mp->type[idx])) 307 return (1); 308 } 309 return (0); 310} 311 312static void 313g_mbrext_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp) 314{ 315 struct g_mbrext_softc *mp; 316 struct g_slicer *gsp; 317 318 g_slice_dumpconf(sb, indent, gp, cp, pp); 319 gsp = gp->softc; 320 mp = gsp->softc; 321 if (pp != NULL) { 322 if (indent == NULL) 323 sbuf_printf(sb, " ty %d", mp->type[pp->index]); 324 else 325 sbuf_printf(sb, "%s<type>%d</type>\n", indent, 326 mp->type[pp->index]); 327 } 328} 329 330static struct g_geom * 331g_mbrext_taste(struct g_class *mp, struct g_provider *pp, int insist __unused) 332{ 333 struct g_geom *gp; 334 struct g_consumer *cp; 335 int error, i, slice; 336 struct g_mbrext_softc *ms; 337 off_t off; 338 u_char *buf; 339 struct dos_partition dp[4]; 340 u_int fwsectors, sectorsize; 341 342 g_trace(G_T_TOPOLOGY, "g_mbrext_taste(%s,%s)", mp->name, pp->name); 343 g_topology_assert(); 344 if (strcmp(pp->geom->class->name, MBR_CLASS_NAME)) 345 return (NULL); 346 gp = g_slice_new(mp, NDOSEXTPART, pp, &cp, &ms, sizeof *ms, 347 g_mbrext_start); 348 if (gp == NULL) 349 return (NULL); 350 g_topology_unlock();
|