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