远景论坛积分规则、等级制度说明远景服务 - 免费开通您的远景博客远景论坛 - 美化区Q&A 移动主站 电信镜像 网通镜像
展望Windows7 关注Win7X.Com赞助远景,在远景网站上刊登广告iPhone 权威中文论坛-WeiPhone注册@pcbeta.com邮箱 邮箱登陆
远景论坛论坛版主联合招募Plus计划看电影,就用快乐影音!远景招募首席美工设计师 详情请进远景论坛制度章程(200810)
发新话题
打印

OSX86引导文件研究

本主题由 TTNK 于 2008-9-30 13:41 限时置顶
来附上一个Startupfiletool.c的源码,有兴趣的可以看看。
引用:
/*
* 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[0];
        file = argv[1];
                       
        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[kSectorSize];
  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[0].startBlock =
    OSSwapHostToBigInt32(allocatedStart);
  vh->startupFile.extents[0].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[k] == 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[startk] = 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 编辑 ]
附件: 您所在的用户组无法下载或查看附件
我的博客
再次声明,所有PM,一律不回。。。
太深奥了,佩服
学习again!!
cpu t2250
主板 945GM
显卡 geforce 7300
内存 1.5 G
网卡marvell
好好 学习
很不错的文字!

慢慢阅读ing……
他一生都在演戏,假装残酷,假装成熟,假装无所谓,但事实上,他一直都很天真.他最后几年没怎么笑过,也许只是因为他不认识自己了
http://www.macgood.com/?fromuid=5432
说心里话,我很高兴看到这个文章,因为我在这第一次体验苹果时,通过这篇文章的一楼,手工修复了苹果的引导,并且,它还能引导XP

很高兴。这几天感触很多,晚上整理一下顺序,写一下感想。
分享知识是一种快乐,海豚乐于助人
博客:黑海豚的直觉 VistaPC.CN
學習了, 謝謝
好好 学习
高手阿,进来学习一下
写得太好了...支持...
我也来说说我个人的发现吧。
Chain0是主引导记录(MBR),因为一个扇区512字节中后面有4X16个字节的分区表以及55 AA两个字节的标识位,所以引导部分只有512-66即446个字节。这446个字节中其实后面还有几个字节是00,没有意义。在用DD写时,因为不同的硬盘分区很可能是不同的,所以只能写入前446字节,不然可能损坏分区表,不能引导。
boot1h是每个分区的引导扇区,位于每个分区的第一个扇区,DOS系统引导时会将其载入。以前DOS系统时如果系统的BOOT扇区是不能引导的,必须用sys命令将其写为可引导的或是在格式化时用/s命令。而后来的NTFS和HFS都不用了。如果WINXP之类的系统有DOS命令行选项的话,就会在C盘根目录bootsect.bin文件,是用来引导DOS系统的。而NTFS系统中会用部分字节用于描述分区的信息,分区大小不同可能会不一样,所以不宜直接覆盖。而HFS的BOOT扇区是完全一样的,可以直接覆盖。
虚拟机修复。没听说,58楼有兴致可否写一贴
iAtkos中的Bootefi貌似是PC-EFI來的,並非無用。。。
楼主的文章我收藏了,装了n次才看到这文章太晚了,看完之后有种茅塞顿开的感觉,知道了以前失败的原因
不错  顶起  

学习
今日终于有幸寻获此贴,颇有收获~

并接看到了很多高手发言~
1.AMD X2 5000+ / Biostar TF520 A2+
Zephy**** 10.5.2 iso刻光盘安装,一切顺利 / 后手工替换破解核心到9.4.0
2.Intel Core2 6600 / MSI-7345
把系统2的硬盘 接在系统1里,GPT分区表,open OSInstall.mpkg直接安装原版到系统2的硬盘里,接着安装10.5.4的补丁,安装变色龙,crack copy AppleDecryption.kext、Disabler.kext;将系统2硬盘安装回本机,开机,原版9.4.0内核引导,进入系统,使用EFI Studio 加入显卡string,重起,显卡正常识别……
远景原来也是有高手滴。。。。
CPU:Core2Duo E7200
主板:技嘉GA-EP31-DS3L
内存:2G DDR2 800 Transecond
显卡:GeForce 8500GT With CI/QE
学习学习
芯片组:intel 965         CPU:Intel T8100 2.1G{正常识别}
内存:2G DDR2 667{正常识别}
显卡:nv 8400GS{QE/CI开启,关机重启不断电}
有线:bcm5906{未识别}
无线:intel4965agn{未识别}->更换在BCM4321,识别成AirPort,正常
声卡:sigmatel 9228[76168384]{有声音,重启无声}
学习下,啃到苹果的日子不会长了
太深渊了。。没装上MAC。体会不了。先收藏先
CPU: Intel Core 2 Duo E7200
主板:GA P35-DS3L                  显卡:蓝宝 HD3650
内存:2G 800MHz                     光驱:先锋216
硬盘:Barracuda 320G              Apple iMac Keyboard
Apple Wireless Mighty Mouse  Power G5 机箱
发新话题