pappplus 发表于 2007-11-29 16:48

更新了/usr/standalone/i386文件夹中所有文件的作用,顶一下。

Envying 发表于 2007-11-29 23:09

看来boot1h(它是一级引导文件)的确不是写的MBR,应该叫VBR(Volume Boot Record分区引导记录),因为写MBR是不能写512字节的,446字节之后有很多的分区信息,是不可能采用相同的文件来定义的。

真有兴趣的还可以继续研究。
1、用dd命令把你的OS X所在硬盘的MBR读出来;
dd if=/dev/diskX of=mbr.bin bs=446 count=1
2、然后与Chain0或boot0比较这个生成的文件看看就知道了;
3、另外,MBR的code部分是实模式的,应该可以直接反汇编出来看的;

参考文献是wiki上关于MBR的介绍。

chindows 发表于 2007-11-29 23:24

好帖子,有料,顶。

Envying 发表于 2007-11-30 13:27

经过比较发现,MBR的内容就是boot0

Envying 发表于 2007-11-30 13:33

再附上一张chain0与VBR(boot1h)的对比。大家可以看一下最后的错误信息对比,是不是很熟悉呀?

jerrykaiser 发表于 2007-11-30 14:29

果然boot0就是抹掉了DPT的MBR
boot1h也只是被写到PBR而已。。

Envying 发表于 2007-11-30 23:07

再补充一点说明:
我的这块硬盘全是HFS+的分区,晚上再贴上SATA(XP)硬盘MBR的内容比比看。/w00t.gif

jerry_work 发表于 2007-12-4 19:01

好身的文章喔,看不懂

masaemon 发表于 2007-12-5 21:42

这么好的帖子,可惜我想保存下来远景都不让。。。。

hdfdisk 发表于 2007-12-5 22:01

BOOT0如果我没记错的话
是写guid分区时必须的

sweec 发表于 2007-12-7 05:13

刚才研究了一下startfiletool的源程序,在每个HFS+的分区最初1024字节后有一个512字节的HFSPlusVolumeHeader,他的定义如下:
struct HFSPlusVolumeHeader
{
UInt16        sig;
UInt16        version;
UInt32        attributes;
UInt32        lastMountedVersion;
UInt32        journalInfoBlock;

UInt32        createDate;
UInt32        modifyDate;
UInt32        backupDate;
UInt32        checkedDate;

UInt32        fileCount;
UInt32        folderCount;

UInt32        blockSize;
UInt32        totalBlocks;
UInt32        freeBlocks;

UInt32        nextAllocation;
UInt32        rsrcClumpSize;
UInt32        dataClumpSize;
HFSCatalogNodeID nextCatalogID;

UInt32        writeCount;
UInt64        encodingsBitmap;

HFSPlusForkData allocationFile;
HFSPlusForkData extentsFile;
HFSPlusForkData catalogFile;
HFSPlusForkData attributesFile;
HFSPlusForkData startupFile;
} __attribute__((packed));

startfiletool的作用是在磁盘上像存储其他文件一样随便找个空余的地方写入boot或者efi_boot,然后更新这个HFSPlusVolumeHeader,最重要的是更新了他的最后那个startupFile项,使它指向写入的boot文件的位置,这才能保证启动的时候调用这个boot,后者完成必要的工作(比如提供欺骗性的EFI信息)后启动mach_kernel.
至于envying前面提到的62kb的大小限制,我觉得是指对boot的要求吧,因为boot1h写在f分区前512字节内,怎么可能这么大呢。

白马 发表于 2007-12-7 16:19

这个是否可以用于解决用TOH抹盘而不能引导的问题呢?

Envying 发表于 2007-12-15 04:01

原帖由 sweec 于 2007-12-6 14:13 发表 https://bbs.pcbeta.com/images/common/back.gif
至于envying前面提到的62kb的大小限制,我觉得是指对boot的要求吧,因为boot1h写在f分区前512字节内,怎么可能这么大呢。

62kb is the limit for boot or boot_efi, these two files are second stage booter are for loading mach_kernel.

wangdongg 发表于 2007-12-27 22:11

支持一下
/sleep.gif

bennyting 发表于 2007-12-28 13:24

先顶了。再慢慢研究pb81

qqdwdbb 发表于 2007-12-28 13:43

写得好深啊,远景难得看到这样的帖子,但对初学者好像太难了,其实用虚拟机修复引导很方便的

aleo 发表于 2008-1-2 08:12

哇 虽然看不怎么明白 但绝对是好文章 也直的好好学习

healy 发表于 2008-1-3 21:21

我看不懂 我还得努力学习

Envying 发表于 2008-1-4 02:12

来附上一个Startupfiletool.c的源码,有兴趣的可以看看。:loveliness:
/*
* startupfiletool - Shantonu Sen <ssen@opendarwin.org>
* Tool to set HFS+ Startup File
* cc -o startupfiletool startupfiletool.c -O0 -g -Wall
*/

#include <libc.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/disk.h>
#include <util.h>
#include <err.h>

#include <hfs/hfs_format.h>
#include <libkern/OSByteOrder.h>

int verbose = 0;

void usage(void);
int writeStartupFile(char *device, char *filedata);
int allocateBlocks(int fd, HFSPlusForkData *allocationFile,
                   uint32_t allocationBlockSize, uint32_t totalBlocks,
                   uint32_t *allocatedBlocks, uint32_t *allocatedStart);
uint64_t mapForkOffset(HFSPlusForkData *fork, uint32_t allocationBlockSize,
                        uint32_t blockNumber);

int main(int argc, char *argv[]) {
        char *device = NULL;
        char *file = NULL;
        int ch;
       
        if(argc == 1)
                usage();
       
        while ((ch = getopt(argc, argv, "v")) != -1) {
                switch(ch) {
                        case 'v':
                                verbose = 1;
                                break;
                        case 'h':
                        default:
                                usage();
                                break;
                }
               
        }
        argc -= optind;
        argv += optind;

        if(argc != 2)
          usage();

       
        device = argv;
        file = argv;
                       
        return writeStartupFile(device, file);
       
        return 0;
}

void usage(void)
{

        fprintf(stderr, "Usage: %s [-v] <raw device> <file>\n", getprogname());
       
        exit(1);
}

#define kSectorSize 512

int writeStartupFile(char *device, char *filedata)
{
int fd, datafd;
int ret;
ssize_t bytesRead, bytesWritten;
uint32_t allocationBlockSize = 0;
uint32_t totalBlocks = 0;
uint64_t logicalSize = 0;
uint32_t deviceBlockSize = 0;
uint64_t deviceBlockCount = 0;
char *datapayload = NULL;
struct stat sb;
char buffer;
HFSPlusVolumeHeader *vh = (HFSPlusVolumeHeader *)buffer;
uint32_t allocatedBlocks = 0, allocatedStart = 0;
ssize_t iobytes;

fd = opendev(device, O_RDWR, 0, NULL);
if(fd < 0)
    err(1, "opendev(%s)", device);

ret = ioctl(fd, DKIOCGETBLOCKSIZE, &deviceBlockSize);
if(ret)
    err(1, "ioctl(DKIOCGETBLOCKSIZE)");

ret = ioctl(fd, DKIOCGETBLOCKCOUNT, &deviceBlockCount);
if(ret)
    err(1, "ioctl(DKIOCGETBLOCKCOUNT)");


bytesRead = pread(fd, buffer, sizeof(buffer), 2*kSectorSize);
if(bytesRead != sizeof(buffer))
    err(1, "pread");

switch(OSSwapBigToHostInt16(vh->signature)) {
case kHFSPlusSigWord:
    printf("HFS+ filesystem detected\n");
    break;
case kHFSXSigWord:
    printf("HFSX filesystem detected\n");
    break;
case kHFSSigWord: {
    HFSMasterDirectoryBlock *mdb = (HFSMasterDirectoryBlock *)vh;
    if(OSSwapBigToHostInt16(mdb->drEmbedSigWord)
       == kHFSPlusSigWord) {
      errx(1, "Wrapped HFS+ filesystem not supported");
    } else {
      errx(1, "HFS (plain) filesystem not supported");
    }
}
    break;
default:
    errx(1, "Unrecognized filesystem");
}

if((OSSwapBigToHostInt32(vh->attributes) & kHFSVolumeUnmountedMask)
   == 0) {
    errx(1, "Filesystem not cleanly unmounted");
}

allocationBlockSize = OSSwapBigToHostInt32(vh->blockSize);

datafd = open(filedata, O_RDONLY, 0400);
if(datafd < 0)
    err(1, "open(%s)", filedata);

ret = fstat(datafd, &sb);
if(ret)
    err(1, "fstat(%s)", filedata);

logicalSize = sb.st_size;
totalBlocks = (logicalSize + allocationBlockSize - 1)/allocationBlockSize;

ret = allocateBlocks(fd, &vh->allocationFile,
                     allocationBlockSize, totalBlocks,
                     &allocatedBlocks, &allocatedStart);
if(ret)
    errc(1, ret, "allocateBlocks of %u failed", totalBlocks);

printf("allocated blocks %u at start %u\n",
       allocatedBlocks, allocatedStart);

vh->freeBlocks = OSSwapHostToBigInt32(OSSwapBigToHostInt32(vh->freeBlocks)
                                        - allocatedBlocks);
vh->writeCount = OSSwapHostToBigInt32(OSSwapBigToHostInt32(vh->writeCount)
                                        + 1);

vh->startupFile.extents.startBlock =
    OSSwapHostToBigInt32(allocatedStart);
vh->startupFile.extents.blockCount =
    OSSwapHostToBigInt32(allocatedBlocks);

vh->startupFile.logicalSize = OSSwapHostToBigInt64(logicalSize);
vh->startupFile.clumpSize = OSSwapHostToBigInt32(allocationBlockSize);
vh->startupFile.totalBlocks= OSSwapHostToBigInt32(allocatedBlocks);

bytesWritten = pwrite(fd, buffer, sizeof(buffer), 2*kSectorSize);
if(bytesWritten != sizeof(buffer))
    err(1, "pwrite HFS+ VH");

bytesWritten = pwrite(fd, buffer, sizeof(buffer),
                        ((uint64_t)deviceBlockSize) * deviceBlockCount - 2*kSectorSize);
if(bytesWritten != sizeof(buffer))
    err(1, "pwrite HFS+ Alt-VH");


iobytes = ((size_t)sb.st_size + allocationBlockSize-1)/allocationBlockSize*allocationBlockSize;
datapayload = malloc(iobytes);
if(read(datafd, datapayload, (size_t)sb.st_size) != (size_t)sb.st_size)
    err(1, "short read of datafd");

if(pwrite(fd, datapayload, iobytes, ((off_t)allocatedStart)*((off_t)allocationBlockSize)) != iobytes)
    err(1, "short write of payload");

free(datapayload);

ret = close(datafd);
if(ret)
    err(1, "close");

ret = close(fd);
if(ret)
    err(1, "close");

return 0;
}

// we traverse the primary extents for the allocation bitmap
// to find space for the startup file.
int allocateBlocks(int fd, HFSPlusForkData *allocationFile,
                   uint32_t allocationBlockSize, uint32_t totalBlocks,
                   uint32_t *allocatedBlocks, uint32_t *allocatedStart)
{
// total number of empty allocation words we need.
uint32_t allocationWords = (totalBlocks + 32 - 1)/32;
HFSPlusForkData bitmapFork;
int i;
uint32_t j;
size_t bufferSize = allocationBlockSize; // read a block at a time
char * buffer = valloc(bufferSize);

printf("Looking for %u words free\n", allocationWords);

if(buffer == NULL)
    err(1, "valloc failed");

bitmapFork = *allocationFile;
bitmapFork.logicalSize = OSSwapBigToHostInt64(bitmapFork.logicalSize);
bitmapFork.clumpSize = OSSwapBigToHostInt32(bitmapFork.clumpSize);
bitmapFork.totalBlocks = OSSwapBigToHostInt32(bitmapFork.totalBlocks);
for(i=0; i < kHFSPlu***tentDensity; i++) {
    bitmapFork.extents.startBlock =
      OSSwapBigToHostInt32(bitmapFork.extents.startBlock);
    bitmapFork.extents.blockCount =
      OSSwapBigToHostInt32(bitmapFork.extents.blockCount);
}

for(j=0; j < bitmapFork.totalBlocks; j++) {
    ssize_t readBytes, writeBytes;
    int contigWordsEmpty = 0;
    uint32_t *ptr;
    int k;
    int foundit = 0;
    off_t readOffset = mapForkOffset(&bitmapFork,
                                     allocationBlockSize,
                                     j);
    printf("reading %qu,%d\n", readOffset, allocationBlockSize);
    readBytes = pread(fd, buffer, allocationBlockSize, readOffset);
    if(readBytes != allocationBlockSize)
      err(1, "pread(%d,%qu)", allocationBlockSize, readOffset);

    ptr = (uint32_t *)buffer;
    for(k=0; k < allocationBlockSize/sizeof(uint32_t); k++) {
      if(ptr == 0x0) {
        contigWordsEmpty++;
        if(contigWordsEmpty == allocationWords) {
          // got it
          int startk = k + 1 - contigWordsEmpty;
          int endk = k;
          *allocatedBlocks = contigWordsEmpty*32;
          *allocatedStart = j*allocationBlockSize*8
          + startk*32;
          for(; startk <= endk; startk++) {
          printf("Marking word %d\n", startk);
          ptr = 0xFFFFFFFF;
          }
          foundit = 1;
          break;
        }
      } else {
        contigWordsEmpty = 0;
      }
    }
   
    if(foundit) {
      // marked the bits as used. Need to write back bitmap
      printf("writing back %qu,%d\n", readOffset, allocationBlockSize);
      writeBytes = pwrite(fd, buffer, allocationBlockSize, readOffset);
      // writeBytes = allocationBlockSize;
      if(writeBytes != allocationBlockSize)
        err(1, "pwrite(%d,%qu)", allocationBlockSize, readOffset);

      break;
    }

}

if(j == bitmapFork.totalBlocks) {
    // didn't allocate it
    return 1;
} else {
    return 0;
}
}

uint64_t mapForkOffset(HFSPlusForkData *fork, uint32_t allocationBlockSize,
                        uint32_t blockNumber)
{
int i;
uint64_t offset = 0xFFFFFFFFFFFFFFFFULL;

for(i=0; i < kHFSPlu***tentDensity; i++) {
    if(blockNumber < fork->extents.blockCount) {
      // in this extent
      offset =
        ((uint64_t)(fork->extents.startBlock + blockNumber))*((uint64_t)allocationBlockSize);
      break;
    } else {
      // make relative to rest of file
      blockNumber -= fork->extents.blockCount;
    }
}

if(i == kHFSPlu***tentDensity)
    errx(1, "Could not map block in fork");

return offset;
}


靠,竟然有部分代码被和谐了!

[ 本帖最后由 Envying 于 2008-1-3 11:14 编辑 ]

housei 发表于 2008-1-4 05:04

太深奥了,佩服pb81
页: 1 2 [3] 4 5 6 7 8
查看完整版本: OSX86引导文件研究