/* * To facilitate booting from CDs, we create a partition for * the boot floppy image embedded in a bootable CD. */ static int part9660(SDunit *unit) { uint8_t buf[2048]; uint32_t a, n; uint8_t *p; if(unit->secsize != 2048) return -1; if(sdbio(unit, &unit->part[0], buf, 2048, 17*2048) < 0) return -1; if(buf[0] || strcmp((char*)buf+1, "CD001\x01EL TORITO SPECIFICATION") != 0) return -1; p = buf+0x47; a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); if(sdbio(unit, &unit->part[0], buf, 2048, a*2048) < 0) return -1; if(memcmp(buf, "\x01\x00\x00\x00", 4) != 0 || memcmp(buf+30, "\x55\xAA", 2) != 0 || buf[0x20] != 0x88) return -1; p = buf+0x28; a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); switch(buf[0x21]){ case 0x01: n = 1200*1024; break; case 0x02: n = 1440*1024; break; case 0x03: n = 2880*1024; break; default: return -1; } n /= 2048; print("found partition %s!cdboot; %lud+%lud\n", unit->name, a, n); sdaddpart(unit, "cdboot", a, a+n); return 0; }
long sdread(Fs *vcrud, void *v, long n) { Scsicrud *crud; long x; crud = (Scsicrud*)vcrud; x = sdbio(crud->unit, crud->part, v, n, crud->offset); if(x > 0) crud->offset += x; return x; }
int tsdbio(SDunit *unit, SDpart *part, void *a, vlong off, int mbr) { uchar *b; if(sdbio(unit, part, a, unit->secsize, off) != unit->secsize){ if(trace) print("%s: read %lud at %lld failed\n", unit->name, unit->secsize, (vlong)part->start*unit->secsize+off); return -1; } b = a; if(mbr && (b[0x1FE] != 0x55 || b[0x1FF] != 0xAA)){ if(trace) print("%s: bad magic %.2ux %.2ux at %lld\n", unit->name, b[0x1FE], b[0x1FF], (vlong)part->start*unit->secsize+off); return -1; } return 0; }
static long sdwrite(Chan* c, void* a, long n, vlong off) { char *f0; int i; uvlong end, start; Cmdbuf *cb; SDifc *ifc; SDreq *req; SDunit *unit; SDev *sdev; switch(TYPE(c->qid)){ default: error(Eperm); case Qtopctl: cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } if(cb->nf == 0) error("empty control message"); f0 = cb->f[0]; cb->f++; cb->nf--; if(strcmp(f0, "config") == 0){ /* wormhole into ugly legacy interface */ legacytopctl(cb); poperror(); free(cb); break; } /* * "ata arg..." invokes sdifc[i]->wtopctl(nil, cb), * where sdifc[i]->name=="ata" and cb contains the args. */ ifc = nil; sdev = nil; for(i=0; sdifc[i]; i++){ if(strcmp(sdifc[i]->name, f0) == 0){ ifc = sdifc[i]; sdev = nil; goto subtopctl; } } /* * "sd1 arg..." invokes sdifc[i]->wtopctl(sdev, cb), * where sdifc[i] and sdev match controller letter "1", * and cb contains the args. */ if(f0[0]=='s' && f0[1]=='d' && f0[2] && f0[3] == 0){ if((sdev = sdgetdev(f0[2])) != nil){ ifc = sdev->ifc; goto subtopctl; } } error("unknown interface"); subtopctl: if(waserror()){ if(sdev) decref(&sdev->r); nexterror(); } if(ifc->wtopctl) ifc->wtopctl(sdev, cb); else error(Ebadctl); poperror(); poperror(); if (sdev) decref(&sdev->r); free(cb); break; case Qctl: cb = parsecmd(a, n); sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->ctl); if(waserror()){ qunlock(&unit->ctl); decref(&sdev->r); free(cb); nexterror(); } if(unit->vers != c->qid.vers) error(Echange); if(cb->nf < 1) error(Ebadctl); if(strcmp(cb->f[0], "part") == 0){ if(cb->nf != 4) error(Ebadctl); if(unit->sectors == 0 && !sdinitpart(unit)) error(Eio); start = strtoull(cb->f[2], 0, 0); end = strtoull(cb->f[3], 0, 0); sdaddpart(unit, cb->f[1], start, end); } else if(strcmp(cb->f[0], "delpart") == 0){ if(cb->nf != 2 || unit->part == nil) error(Ebadctl); sddelpart(unit, cb->f[1]); } else if(unit->dev->ifc->wctl) unit->dev->ifc->wctl(unit, cb); else error(Ebadctl); qunlock(&unit->ctl); decref(&sdev->r); poperror(); free(cb); break; case Qraw: sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->raw); if(waserror()){ qunlock(&unit->raw); decref(&sdev->r); nexterror(); } switch(unit->state){ case Rawcmd: if(n < 6 || n > sizeof(req->cmd)) error(Ebadarg); if((req = malloc(sizeof(SDreq))) == nil) error(Enomem); req->unit = unit; memmove(req->cmd, a, n); req->clen = n; req->flags = SDnosense; req->status = ~0; unit->req = req; unit->state = Rawdata; break; case Rawstatus: unit->state = Rawcmd; free(unit->req); unit->req = nil; error(Ebadusefd); case Rawdata: unit->state = Rawstatus; unit->req->write = 1; n = sdrio(unit->req, a, n); } qunlock(&unit->raw); decref(&sdev->r); poperror(); break; case Qpart: return sdbio(c, 1, a, n, off); } return n; }
static long sdread(Chan *c, void *a, long n, vlong off) { char *p, *e, *buf; SDpart *pp; SDunit *unit; SDev *sdev; ulong offset; int i, l, m, status; offset = off; switch(TYPE(c->qid)){ default: error(Eperm); case Qtopctl: m = 64*1024; /* room for register dumps */ p = buf = malloc(m); if(p == nil) error(Enomem); e = p + m; qlock(&devslock); for(i = 0; i < nelem(devs); i++){ sdev = devs[i]; if(sdev && sdev->ifc->rtopctl) p = sdev->ifc->rtopctl(sdev, p, e); } qunlock(&devslock); n = readstr(off, a, n, buf); free(buf); return n; case Qtopdir: case Qunitdir: return devdirread(c, a, n, 0, 0, sdgen); case Qctl: sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; m = 16*1024; /* room for register dumps */ p = malloc(m); if(p == nil) error(Enomem); l = snprint(p, m, "inquiry %.48s\n", (char*)unit->inquiry+8); qlock(&unit->ctl); /* * If there's a device specific routine it must * provide all information pertaining to night geometry * and the garscadden trains. */ if(unit->dev->ifc->rctl) l += unit->dev->ifc->rctl(unit, p+l, m-l); if(unit->sectors == 0) sdinitpart(unit); if(unit->sectors){ if(unit->dev->ifc->rctl == nil) l += snprint(p+l, m-l, "geometry %llud %lud\n", unit->sectors, unit->secsize); pp = unit->part; for(i = 0; i < unit->npart; i++){ if(pp->valid) l += snprint(p+l, m-l, "part %s %llud %llud\n", pp->name, pp->start, pp->end); pp++; } } qunlock(&unit->ctl); decref(&sdev->r); l = readstr(offset, a, n, p); free(p); return l; case Qraw: sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); unit = sdev->unit[UNIT(c->qid)]; qlock(&unit->raw); if(waserror()){ qunlock(&unit->raw); decref(&sdev->r); nexterror(); } if(unit->state == Rawdata){ unit->state = Rawstatus; i = sdrio(unit->req, a, n); } else if(unit->state == Rawstatus){ status = unit->req->status; unit->state = Rawcmd; free(unit->req); unit->req = nil; i = readnum(0, a, n, status, NUMSIZE); } else i = 0; qunlock(&unit->raw); decref(&sdev->r); poperror(); return i; case Qpart: return sdbio(c, 0, a, n, off); } }