merge
This commit is contained in:
commit
4e9d8a7435
4 changed files with 413 additions and 66 deletions
|
@ -1,20 +1,42 @@
|
||||||
#include <u.h>
|
#include <u.h>
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
|
|
||||||
|
#define GETSHORT(p) (*(ushort *)(p))
|
||||||
|
#define GETLONG(p) (*(uint *)(p))
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
Sectsz = 0x200,
|
Sectsz = 0x200,
|
||||||
Dirsz = 0x20,
|
Dirsz = 0x20,
|
||||||
Maxpath = 64,
|
Maxpath = 64,
|
||||||
|
Fat12 = 1,
|
||||||
|
Fat16 = 2,
|
||||||
|
Fat32 = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Extend Extend;
|
typedef struct Extend Extend;
|
||||||
typedef struct Dir Dir;
|
typedef struct Dir Dir;
|
||||||
typedef struct Pbs Pbs;
|
typedef struct Pbs Pbs;
|
||||||
|
typedef struct Fat Fat;
|
||||||
|
|
||||||
|
struct Fat
|
||||||
|
{
|
||||||
|
ulong ver;
|
||||||
|
int drive;
|
||||||
|
ulong clustsize;
|
||||||
|
ulong eofmark;
|
||||||
|
ulong partlba;
|
||||||
|
ulong fatlba;
|
||||||
|
ulong dirstart; /* LBA for FAT16, cluster for FAT32 */
|
||||||
|
ulong dirents;
|
||||||
|
ulong datalba;
|
||||||
|
};
|
||||||
|
|
||||||
struct Extend
|
struct Extend
|
||||||
{
|
{
|
||||||
int drive;
|
Fat *fat;
|
||||||
ulong lba;
|
ulong lba;
|
||||||
|
ulong clust;
|
||||||
|
ulong lbaoff;
|
||||||
ulong len;
|
ulong len;
|
||||||
uchar *rp;
|
uchar *rp;
|
||||||
uchar *ep;
|
uchar *ep;
|
||||||
|
@ -53,12 +75,34 @@ struct Pbs
|
||||||
uchar nheads[2];
|
uchar nheads[2];
|
||||||
uchar nhidden[4];
|
uchar nhidden[4];
|
||||||
uchar bigvolsize[4];
|
uchar bigvolsize[4];
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
uchar driveno;
|
uchar driveno;
|
||||||
uchar reserved0;
|
uchar reserved0;
|
||||||
uchar bootsig;
|
uchar bootsig;
|
||||||
uchar volid[4];
|
uchar volid[4];
|
||||||
uchar label[11];
|
uchar label[11];
|
||||||
uchar type[8];
|
uchar type[8];
|
||||||
|
} fat16;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uchar fatsize[4];
|
||||||
|
uchar flags[2];
|
||||||
|
uchar ver[2];
|
||||||
|
uchar rootclust[4];
|
||||||
|
uchar fsinfo[2];
|
||||||
|
uchar bootbak[2];
|
||||||
|
uchar reserved0[12];
|
||||||
|
uchar driveno;
|
||||||
|
uchar reserved1;
|
||||||
|
uchar bootsig;
|
||||||
|
uchar volid[4];
|
||||||
|
uchar label[11];
|
||||||
|
uchar type[8];
|
||||||
|
} fat32;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
int readsect(ulong drive, ulong lba, void *buf);
|
int readsect(ulong drive, ulong lba, void *buf);
|
||||||
|
@ -68,14 +112,47 @@ unload(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ulong
|
||||||
|
readnext(Extend *ex, ulong clust)
|
||||||
|
{
|
||||||
|
Fat *fat = ex->fat;
|
||||||
|
uint b = fat->ver;
|
||||||
|
ulong sect, off;
|
||||||
|
|
||||||
|
sect = clust * b / Sectsz;
|
||||||
|
off = clust * b % Sectsz;
|
||||||
|
if(readsect(fat->drive, fat->fatlba + sect, ex->buf))
|
||||||
|
memset(ex->buf, 0xff, 4);
|
||||||
|
switch(fat->ver){
|
||||||
|
case Fat16:
|
||||||
|
return GETSHORT(&ex->buf[off]);
|
||||||
|
case Fat32:
|
||||||
|
return GETLONG(&ex->buf[off])& 0x0fffffff;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
read(void *f, void *data, int len)
|
read(void *f, void *data, int len)
|
||||||
{
|
{
|
||||||
Extend *ex = f;
|
Extend *ex = f;
|
||||||
|
Fat *fat = ex->fat;
|
||||||
|
|
||||||
if(ex->len > 0 && ex->rp >= ex->ep)
|
if(ex->len > 0 && ex->rp >= ex->ep){
|
||||||
if(readsect(ex->drive, ex->lba++, ex->rp = ex->buf))
|
if(ex->clust != ~0U){
|
||||||
|
if(ex->lbaoff % fat->clustsize == 0){
|
||||||
|
if((ex->clust >> 4) == fat->eofmark)
|
||||||
return -1;
|
return -1;
|
||||||
|
ex->lbaoff = (ex->clust - 2) * fat->clustsize;
|
||||||
|
putc('.');
|
||||||
|
ex->clust = readnext(ex, ex->clust);
|
||||||
|
ex->lba = ex->lbaoff + fat->datalba;
|
||||||
|
}
|
||||||
|
ex->lbaoff++;
|
||||||
|
}
|
||||||
|
if(readsect(fat->drive, ex->lba++, ex->rp = ex->buf))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if(ex->len < len)
|
if(ex->len < len)
|
||||||
len = ex->len;
|
len = ex->len;
|
||||||
if(len > (ex->ep - ex->rp))
|
if(len > (ex->ep - ex->rp))
|
||||||
|
@ -87,42 +164,21 @@ read(void *f, void *data, int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
close(void *f)
|
open(Fat *fat, void *f, ulong lba)
|
||||||
{
|
{
|
||||||
Extend *ex = f;
|
Extend *ex = f;
|
||||||
|
|
||||||
ex->drive = 0;
|
ex->fat = fat;
|
||||||
ex->lba = 0;
|
ex->lba = lba;
|
||||||
ex->len = 0;
|
ex->len = 0;
|
||||||
|
ex->lbaoff = 0;
|
||||||
|
ex->clust = ~0U;
|
||||||
ex->rp = ex->ep = ex->buf + Sectsz;
|
ex->rp = ex->ep = ex->buf + Sectsz;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ulong
|
void
|
||||||
rootlba(Extend *fat)
|
close(void *)
|
||||||
{
|
{
|
||||||
ulong lba;
|
|
||||||
Pbs *p = (Pbs*)fat->buf;
|
|
||||||
|
|
||||||
lba = fat->lba;
|
|
||||||
lba += *((ushort*)p->nreserv);
|
|
||||||
lba += *((ushort*)p->fatsize) * p->nfats;
|
|
||||||
return lba;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ulong
|
|
||||||
dirlba(Extend *fat, Dir *d)
|
|
||||||
{
|
|
||||||
ulong clust;
|
|
||||||
ulong dirs;
|
|
||||||
ulong lba;
|
|
||||||
Pbs *p = (Pbs*)fat->buf;
|
|
||||||
|
|
||||||
lba = rootlba(fat);
|
|
||||||
dirs = *((ushort*)p->rootsize);
|
|
||||||
lba += (dirs * Dirsz + Sectsz-1) / Sectsz;
|
|
||||||
clust = *((ushort*)d->starthi)<<16 | *((ushort*)d->startlo);
|
|
||||||
lba += (clust - 2) * p->clustsize;
|
|
||||||
return lba;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -155,18 +211,27 @@ dirname(Dir *d, char buf[Maxpath])
|
||||||
return x - buf;
|
return x - buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ulong
|
||||||
|
dirclust(Dir *d)
|
||||||
|
{
|
||||||
|
return *((ushort*)d->starthi)<<16 | *((ushort*)d->startlo);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fatwalk(Extend *ex, Extend *fat, char *path)
|
fatwalk(Extend *ex, Fat *fat, char *path)
|
||||||
{
|
{
|
||||||
char name[Maxpath], *end;
|
char name[Maxpath], *end;
|
||||||
Pbs *pbs = (Pbs*)fat->buf;
|
|
||||||
int i, j;
|
int i, j;
|
||||||
Dir d;
|
Dir d;
|
||||||
|
|
||||||
close(ex);
|
if(fat->ver == Fat32){
|
||||||
ex->drive = fat->drive;
|
open(fat, ex, 0);
|
||||||
ex->lba = rootlba(fat);
|
ex->clust = fat->dirstart;
|
||||||
ex->len = *((ushort*)pbs->rootsize) * Dirsz;
|
ex->len = ~0U;
|
||||||
|
}else{
|
||||||
|
open(fat, ex, fat->dirstart);
|
||||||
|
ex->len = fat->dirents * Dirsz;
|
||||||
|
}
|
||||||
for(;;){
|
for(;;){
|
||||||
if(readn(ex, &d, Dirsz) != Dirsz)
|
if(readn(ex, &d, Dirsz) != Dirsz)
|
||||||
break;
|
break;
|
||||||
|
@ -178,25 +243,81 @@ fatwalk(Extend *ex, Extend *fat, char *path)
|
||||||
end = path + strlen(path);
|
end = path + strlen(path);
|
||||||
j = end - path;
|
j = end - path;
|
||||||
if(i == j && memcmp(name, path, j) == 0){
|
if(i == j && memcmp(name, path, j) == 0){
|
||||||
ex->rp = ex->ep;
|
open(fat, ex, 0);
|
||||||
ex->lba = dirlba(fat, &d);
|
ex->clust = dirclust(&d);
|
||||||
ex->len = *((ulong*)d.len);
|
ex->len = *((ulong*)d.len);
|
||||||
if(*end == 0)
|
if(*end == 0)
|
||||||
return 0;
|
return 0;
|
||||||
else if(d.attr & 0x10){
|
else if(d.attr & 0x10){
|
||||||
ex->len = pbs->clustsize * Sectsz;
|
ex->len = fat->clustsize * Sectsz;
|
||||||
path = end;
|
path = end;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(ex);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
findfat(Extend *fat, int drive)
|
conffat(Fat *fat, void *buf)
|
||||||
|
{
|
||||||
|
Pbs *p = buf;
|
||||||
|
uint fatsize, volsize, datasize, reserved;
|
||||||
|
uint ver, dirsize, dirents, clusters;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if(GETSHORT(p->sectsize) != Sectsz){
|
||||||
|
print("sectsize != 512\r\n");
|
||||||
|
halt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load values from fat */
|
||||||
|
fatsize = GETSHORT(p->fatsize);
|
||||||
|
if(fatsize == 0)
|
||||||
|
fatsize = GETLONG(p->fat32.fatsize);
|
||||||
|
volsize = GETSHORT(p->volsize);
|
||||||
|
if(volsize == 0)
|
||||||
|
volsize = GETLONG(p->bigvolsize);
|
||||||
|
reserved = GETSHORT(p->nreserv);
|
||||||
|
dirents = GETSHORT(p->rootsize);
|
||||||
|
dirsize = (dirents * Dirsz + Sectsz - 1) / Sectsz;
|
||||||
|
datasize = volsize - (reserved + fatsize * p->nfats + dirsize);
|
||||||
|
clusters = datasize / p->clustsize;
|
||||||
|
|
||||||
|
/* determine fat type */
|
||||||
|
if(clusters < 4085)
|
||||||
|
ver = Fat12;
|
||||||
|
else if(clusters < 65525)
|
||||||
|
ver = Fat16;
|
||||||
|
else
|
||||||
|
ver = Fat32;
|
||||||
|
|
||||||
|
/* another check */
|
||||||
|
if(ver == Fat12){
|
||||||
|
print("TODO: implement FAT12\r\n");
|
||||||
|
halt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill FAT descriptor */
|
||||||
|
fat->ver = ver;
|
||||||
|
fat->dirents = dirents;
|
||||||
|
fat->clustsize = p->clustsize;
|
||||||
|
fat->fatlba = fat->partlba + reserved;
|
||||||
|
fat->dirstart = fat->fatlba + fatsize * p->nfats;
|
||||||
|
if(ver == Fat32){
|
||||||
|
fat->datalba = fat->dirstart;
|
||||||
|
fat->dirstart = GETLONG(p->fat32.rootclust);
|
||||||
|
fat->eofmark = 0xffffff;
|
||||||
|
}else{
|
||||||
|
fat->datalba = fat->dirstart + dirsize;
|
||||||
|
fat->eofmark = 0xfff;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
findfat(Fat *fat, int drive)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
uchar status;
|
uchar status;
|
||||||
|
@ -206,20 +327,22 @@ findfat(Extend *fat, int drive)
|
||||||
uchar lba[4];
|
uchar lba[4];
|
||||||
uchar len[4];
|
uchar len[4];
|
||||||
} *p;
|
} *p;
|
||||||
|
uchar buf[Sectsz];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(readsect(drive, 0, fat->buf))
|
if(readsect(drive, 0, buf))
|
||||||
return -1;
|
return -1;
|
||||||
if(fat->buf[0x1fe] != 0x55 || fat->buf[0x1ff] != 0xAA)
|
if(buf[0x1fe] != 0x55 || buf[0x1ff] != 0xAA)
|
||||||
return -1;
|
return -1;
|
||||||
p = (void*)&fat->buf[0x1be];
|
p = (void*)&buf[0x1be];
|
||||||
for(i=0; i<4; i++){
|
for(i=0; i<4; i++){
|
||||||
if(p[i].status != 0x80)
|
if(p[i].status != 0x80)
|
||||||
continue;
|
continue;
|
||||||
close(fat);
|
|
||||||
fat->drive = drive;
|
fat->drive = drive;
|
||||||
fat->lba = *((ulong*)p[i].lba);
|
fat->partlba = *((ulong*)p[i].lba);
|
||||||
if(readsect(drive, fat->lba, fat->buf))
|
if(readsect(drive, fat->partlba, buf))
|
||||||
|
continue;
|
||||||
|
if(conffat(fat, buf))
|
||||||
continue;
|
continue;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -231,12 +354,14 @@ start(void *sp)
|
||||||
{
|
{
|
||||||
char path[Maxpath], *kern;
|
char path[Maxpath], *kern;
|
||||||
int drive;
|
int drive;
|
||||||
Extend fat, ex;
|
Extend ex;
|
||||||
|
Fat fat;
|
||||||
void *f;
|
void *f;
|
||||||
|
|
||||||
/* drive passed in DL */
|
/* drive passed in DL */
|
||||||
drive = ((ushort*)sp)[5] & 0xFF;
|
drive = ((ushort*)sp)[5] & 0xFF;
|
||||||
|
|
||||||
|
print("9bootfat\r\n");
|
||||||
if(findfat(&fat, drive)){
|
if(findfat(&fat, drive)){
|
||||||
print("no fat\r\n");
|
print("no fat\r\n");
|
||||||
halt();
|
halt();
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#define RELOC 0x7c00
|
#define RELOC 0x7c00
|
||||||
|
|
||||||
TEXT _magic(SB), $0
|
TEXT _magic(SB), $0
|
||||||
BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */
|
BYTE $0xEB; BYTE $0x58; /* jmp .+ 0x58 (_start0x5A) */
|
||||||
BYTE $0x90 /* nop */
|
BYTE $0x90 /* nop */
|
||||||
TEXT _version(SB), $0
|
TEXT _version(SB), $0
|
||||||
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
|
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
|
||||||
|
@ -35,9 +35,26 @@ TEXT _nhiddenhi(SB), $0
|
||||||
BYTE $0x00; BYTE $0x00;
|
BYTE $0x00; BYTE $0x00;
|
||||||
TEXT _bigvolsize(SB), $0
|
TEXT _bigvolsize(SB), $0
|
||||||
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
|
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
|
||||||
|
/* FAT32 structure, starting @0x24 */
|
||||||
|
TEXT _fatsz32(SB), $0
|
||||||
|
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
|
||||||
|
TEXT _extflags(SB), $0
|
||||||
|
BYTE $0x00; BYTE $0x00
|
||||||
|
TEXT _fsver(SB), $0
|
||||||
|
BYTE $0x00; BYTE $0x00
|
||||||
|
TEXT _rootclust(SB), $0
|
||||||
|
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
|
||||||
|
TEXT _fsinfo(SB), $0
|
||||||
|
BYTE $0x00; BYTE $0x00
|
||||||
|
TEXT _bkboot(SB), $0
|
||||||
|
BYTE $0x00; BYTE $0x00
|
||||||
|
TEXT _reserved0(SB), $0
|
||||||
|
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
|
||||||
|
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
|
||||||
|
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
|
||||||
TEXT _driveno(SB), $0
|
TEXT _driveno(SB), $0
|
||||||
BYTE $0x00
|
BYTE $0x00
|
||||||
TEXT _reserved0(SB), $0
|
TEXT _reserved1(SB), $0
|
||||||
BYTE $0x00
|
BYTE $0x00
|
||||||
TEXT _bootsig(SB), $0
|
TEXT _bootsig(SB), $0
|
||||||
BYTE $0x00
|
BYTE $0x00
|
||||||
|
@ -49,9 +66,9 @@ TEXT _label(SB), $0
|
||||||
BYTE $0x00; BYTE $0x00; BYTE $0x00
|
BYTE $0x00; BYTE $0x00; BYTE $0x00
|
||||||
TEXT _type(SB), $0
|
TEXT _type(SB), $0
|
||||||
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
|
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
|
||||||
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
|
BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
|
||||||
|
|
||||||
_start0x3E:
|
_start0x5A:
|
||||||
CLI
|
CLI
|
||||||
CLR(rAX)
|
CLR(rAX)
|
||||||
MTSR(rAX, rSS) /* 0000 -> rSS */
|
MTSR(rAX, rSS) /* 0000 -> rSS */
|
||||||
|
|
|
@ -442,9 +442,9 @@ dosfs(int dofat, int dopbs, Disk *disk, char *label, int argc, char *argv[], int
|
||||||
memmove(b->version, "Plan9.00", sizeof(b->version));
|
memmove(b->version, "Plan9.00", sizeof(b->version));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add bootstrapping code; assume it starts
|
* Add bootstrapping code; offset is
|
||||||
* at 0x3E (the destination of the jump we just
|
* determined from short jump (0xEB 0x??)
|
||||||
* wrote to b->magic).
|
* instruction.
|
||||||
*/
|
*/
|
||||||
if(dopbs) {
|
if(dopbs) {
|
||||||
pbsbuf = malloc(secsize);
|
pbsbuf = malloc(secsize);
|
||||||
|
@ -466,11 +466,15 @@ dosfs(int dofat, int dopbs, Disk *disk, char *label, int argc, char *argv[], int
|
||||||
memmove(pbsbuf, bootprog, sizeof(bootprog));
|
memmove(pbsbuf, bootprog, sizeof(bootprog));
|
||||||
npbs = nbootprog;
|
npbs = nbootprog;
|
||||||
}
|
}
|
||||||
if(npbs <= 0x3E)
|
n = buf[1] + 2;
|
||||||
|
if(npbs <= 0x3 || npbs < n)
|
||||||
fprint(2, "warning: pbs too small\n");
|
fprint(2, "warning: pbs too small\n");
|
||||||
else
|
else if(buf[0] != 0xEB)
|
||||||
memmove(buf+0x3E, pbsbuf+0x3E, npbs-0x3E);
|
fprint(2, "warning: pbs doesn't start with short jump\n");
|
||||||
|
else{
|
||||||
|
memmove(buf, pbsbuf, 3);
|
||||||
|
memmove(buf+n, pbsbuf+n, npbs-n);
|
||||||
|
}
|
||||||
free(pbsbuf);
|
free(pbsbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,6 +562,11 @@ if(chatty) print("driveno = %ux\n", b->driveno);
|
||||||
b->bootsig = 0x29;
|
b->bootsig = 0x29;
|
||||||
x = disk->offset + b->nfats*fatsecs + nresrv;
|
x = disk->offset + b->nfats*fatsecs + nresrv;
|
||||||
PUTLONG(b->volid, x);
|
PUTLONG(b->volid, x);
|
||||||
|
/*
|
||||||
|
* FAT32 9boot PBS requires volid at this
|
||||||
|
* offset even for FAT16/FAT12 partitions.
|
||||||
|
*/
|
||||||
|
PUTLONG(b->volid+28, x);
|
||||||
if(chatty) print("volid = %lux %lux\n", x, GETLONG(b->volid));
|
if(chatty) print("volid = %lux %lux\n", x, GETLONG(b->volid));
|
||||||
memmove(b->label, label, sizeof(b->label));
|
memmove(b->label, label, sizeof(b->label));
|
||||||
sprint(r, "FAT%d ", fatbits);
|
sprint(r, "FAT%d ", fatbits);
|
||||||
|
|
196
sys/src/cmd/unix/mbrfix.c
Normal file
196
sys/src/cmd/unix/mbrfix.c
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef unsigned long long vlong;
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
Sectsz = 0x200,
|
||||||
|
Psectsz = 11,
|
||||||
|
Pclustsc = 13,
|
||||||
|
Presvd = 14,
|
||||||
|
Pnumfat = 16,
|
||||||
|
Pfatsz = 22,
|
||||||
|
Pfatsz32 = 36,
|
||||||
|
Pvolid = 67,
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
readn(int f, void *av, int n)
|
||||||
|
{
|
||||||
|
char *a;
|
||||||
|
int m, t;
|
||||||
|
a = av;
|
||||||
|
t = 0;
|
||||||
|
while(t < n){
|
||||||
|
m = read(f, a+t, n-t);
|
||||||
|
if(m <= 0){
|
||||||
|
if(t == 0)
|
||||||
|
return m;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
t += m;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sysfatal(char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
vfprintf(stderr, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
readsect(int fd, uint n, void *data)
|
||||||
|
{
|
||||||
|
loff_t off;
|
||||||
|
|
||||||
|
off = (loff_t) n * Sectsz;
|
||||||
|
if(llseek(fd, off, SEEK_SET) != off)
|
||||||
|
sysfatal("seek to sector 0x%x failed", n);
|
||||||
|
if(readn(fd, data, Sectsz) != Sectsz)
|
||||||
|
sysfatal("short read: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
writesect(int fd, uint n, void *data)
|
||||||
|
{
|
||||||
|
loff_t off;
|
||||||
|
|
||||||
|
off = (loff_t) n * Sectsz;
|
||||||
|
if(llseek(fd, off, SEEK_SET) != off)
|
||||||
|
sysfatal("seek to sector 0x%x failed", n);
|
||||||
|
if(write(fd, data, Sectsz) != Sectsz)
|
||||||
|
sysfatal("short write: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint
|
||||||
|
getulong(uchar *s)
|
||||||
|
{
|
||||||
|
return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
putulong(uchar *s, uint n)
|
||||||
|
{
|
||||||
|
*s++ = n & 0xff;
|
||||||
|
*s++ = (n >> 8) & 0xff;
|
||||||
|
*s++ = (n >> 16) & 0xff;
|
||||||
|
*s++ = (n >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint
|
||||||
|
getushort(uchar *s)
|
||||||
|
{
|
||||||
|
return s[0] | (s[1] << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
checksig(uchar *s)
|
||||||
|
{
|
||||||
|
return s[0x1fe] == 0x55 && s[0x1ff] == 0xaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fixpbs(uchar *pbs, uchar *pbs9, uint lba)
|
||||||
|
{
|
||||||
|
uint a;
|
||||||
|
uint fatsz, resvd, numfat;
|
||||||
|
|
||||||
|
numfat = pbs[Pnumfat];
|
||||||
|
fatsz = getushort(&pbs[Pfatsz]);
|
||||||
|
if(fatsz == 0)
|
||||||
|
fatsz = getulong(&pbs[Pfatsz32]);
|
||||||
|
resvd = getushort(&pbs[Presvd]);
|
||||||
|
|
||||||
|
a = pbs9[1] + 2;
|
||||||
|
memcpy(pbs, pbs9, 3);
|
||||||
|
memcpy(pbs+a, pbs9+a, Sectsz-a-2);
|
||||||
|
a = lba + numfat * fatsz + resvd;
|
||||||
|
printf("Xroot=%x\n", a);
|
||||||
|
putulong(&pbs[Pvolid], a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int dev, fd, i;
|
||||||
|
uchar mbr9[Sectsz], pbs9[Sectsz];
|
||||||
|
uchar mbr[Sectsz], pbs[Sectsz];
|
||||||
|
uint lba;
|
||||||
|
int part, want;
|
||||||
|
char *mbrfn, *pbsfn, *devfn;
|
||||||
|
|
||||||
|
if(argc < 4)
|
||||||
|
sysfatal("usage: <device> <mbrfile> <pbsfile> [part]");
|
||||||
|
devfn = argv[1];
|
||||||
|
mbrfn = argv[2];
|
||||||
|
pbsfn = argv[3];
|
||||||
|
want = argc >= 5 ? atoi(argv[4]) : -1;
|
||||||
|
part = -1;
|
||||||
|
|
||||||
|
dev = open(devfn, O_RDWR);
|
||||||
|
if(dev < 0)
|
||||||
|
sysfatal("%s: %m", devfn);
|
||||||
|
|
||||||
|
if((fd = open(mbrfn, O_RDONLY)) < 0)
|
||||||
|
sysfatal("%s: %m", mbrfn);
|
||||||
|
if(readn(fd, mbr9, Sectsz) < 3)
|
||||||
|
sysfatal("%s: too short", mbrfn);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
fd = open(pbsfn, O_RDONLY);
|
||||||
|
if(fd < 0)
|
||||||
|
sysfatal("%s: %m", pbsfn);
|
||||||
|
if(readn(fd, pbs9, Sectsz) < 3)
|
||||||
|
sysfatal("%s: too short", pbsfn);
|
||||||
|
if(pbs9[0] != 0xeb)
|
||||||
|
sysfatal("first byte of pbs not a short jump");
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
readsect(dev, 0, mbr);
|
||||||
|
if(!checksig(mbr))
|
||||||
|
sysfatal("sector 0 is missing signature");
|
||||||
|
for(i=0; i<4; i++){
|
||||||
|
if(mbr[0x1be + i*16] == 0x80 && (part == -1 || i == want))
|
||||||
|
part = i;
|
||||||
|
}
|
||||||
|
if(part == -1)
|
||||||
|
sysfatal("no bootable partitions found");
|
||||||
|
if(want != -1 && part != want)
|
||||||
|
sysfatal("partition %d is not bootable", want);
|
||||||
|
|
||||||
|
lba = getulong(&mbr[0x1be + part*16 + 8]);
|
||||||
|
if(lba == 0)
|
||||||
|
sysfatal("partition %d has zero LBA", part);
|
||||||
|
|
||||||
|
readsect(dev, lba, pbs);
|
||||||
|
if(!checksig(pbs))
|
||||||
|
sysfatal("partition %d (LBA=0x%x) is missing signaure", part, lba);
|
||||||
|
if(getushort(&pbs[Psectsz]) != 512)
|
||||||
|
sysfatal("sector size not 512");
|
||||||
|
|
||||||
|
printf("using partition %d, LBA=0x%x\n", part, lba);
|
||||||
|
memcpy(mbr, mbr9, 446);
|
||||||
|
fixpbs(pbs, pbs9, lba);
|
||||||
|
|
||||||
|
writesect(dev, 0, mbr);
|
||||||
|
writesect(dev, lba, pbs);
|
||||||
|
|
||||||
|
close(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue