Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 04 Jun 2012 18:40:08 +0000
From:      emc2@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r237076 - soc2012/emc2/hfsimg
Message-ID:  <20120604184008.EC1AB106564A@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emc2
Date: Mon Jun  4 18:40:08 2012
New Revision: 237076
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237076

Log:
  Added some code for creating HFS filesystem images containing a boot loader.
  This code is not complete, but it's probably a good idea to get it into
  version control.

Added:
  soc2012/emc2/hfsimg/
  soc2012/emc2/hfsimg/Makefile
  soc2012/emc2/hfsimg/hfs.c
  soc2012/emc2/hfsimg/hfsimg.8
  soc2012/emc2/hfsimg/main.c

Added: soc2012/emc2/hfsimg/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2012/emc2/hfsimg/Makefile	Mon Jun  4 18:40:08 2012	(r237076)
@@ -0,0 +1,8 @@
+.include <bsd.own.mk>
+
+MAN1=
+MAN8=hfsimg.8
+PROG=hfsimg
+SRCS=main.c hfs.c
+
+.include <bsd.prog.mk>
\ No newline at end of file

Added: soc2012/emc2/hfsimg/hfs.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2012/emc2/hfsimg/hfs.c	Mon Jun  4 18:40:08 2012	(r237076)
@@ -0,0 +1,238 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+
+#include "hfs.h"
+
+#define HFS_PROLOG_SIZE 1024
+#define HFS_EPILOG_SIZE 512
+#define HFS_ATTRIBUTES 0x100
+#define HFS_RESERVED 0
+#define HFS_FORK_DATA_SIZE 80
+#define HFS_TIME_OFFSET (60 * 60 * 24 * 365 * 66)
+#define HFS_BLOCK_SIZE 512
+#define HFS_CATALOG_NODE_SIZE 8192
+
+#define SYSTEM_DIR_CNID 16
+#define LIBRARY_DIR_CNID 17
+#define CORESERVICES_DIR_CNID 18
+#define BOOTEFI_CNID 19
+
+#define ZEROES_SIZE (HFS_PROLOG_SIZE > HFS_EPILOG_SIZE ?	\
+		     HFS_PROLOG_SIZE : HFS_EPILOG_SIZE)
+
+static const uint8_t zeroes[ZEROES_SIZE] = { 0 };
+static uint8_t block[HFS_BLOCK_SIZE];
+static uint8_t node[HFS_CATALOG_NODE_SIZE];
+
+static int write_hfs_prolog(FILE* const restrict file) {
+
+  const int count = fwrite(zeroes, 1, HFS_PROLOG_SIZE, file);
+
+  return count == HFS_PROLOG_SIZE ? 0 : -1;
+
+}
+
+static uint32_t get_time(void) {
+
+  const time_t currtime = time(NULL);
+
+  if(currtime != (time_t)-1)
+    return HFS_TIME_OFFSET + currtime;
+
+  else
+    return (uint32_t)-1;
+
+};
+
+static void init_null_fork_data(void* const restrict ptr) {
+
+  uint32_t* const clumpsize = (uint32_t*)((uint8_t*)ptr + 8);
+
+  memset(ptr, 0, HFS_FORK_DATA_SIZE);
+  clumpsize[0] = HFS_BLOCK_SIZE;
+
+}
+
+static int write_hfs_volume_header(FILE* const restrict file) {
+
+  const uint32_t currtime = get_time();
+
+  if(currtime != (uint32_t)-1) {
+
+    uint8_t* const sig = block;
+    uint16_t* const version = (uint16_t*)(block + 2);
+    uint32_t* const attrs = (uint32_t*)(block + 4);
+    uint8_t* const lastmountvers = block + 8;
+    uint32_t* const journalinfo = (uint32_t*)(block + 12);
+    uint32_t* const createdate = (uint32_t*)(block + 16);
+    uint32_t* const moddate = (uint32_t*)(block + 20);
+    uint32_t* const backupdate = (uint32_t*)(block + 24);
+    uint32_t* const checkdate = (uint32_t*)(block + 28);
+    uint32_t* const filecount = (uint32_t*)(block + 32);
+    uint32_t* const foldercount = (uint32_t*)(block + 36);
+    uint32_t* const blocksize = (uint32_t*)(block + 40);
+    uint32_t* const totalblocks = (uint32_t*)(block + 44);
+    uint32_t* const freeblocks = (uint32_t*)(block + 48);
+    uint32_t* const nextalloc = (uint32_t*)(block + 52);
+    uint32_t* const rsrcclumpsize = (uint32_t*)(block + 56);
+    uint32_t* const dataclumpsize = (uint32_t*)(block + 60);
+    uint32_t* const catalogid = (uint32_t*)(block + 64);
+    uint32_t* const writecount = (uint32_t*)(block + 68);
+    uint64_t* const encodings = (uint64_t*)(block + 72);
+    uint32_t* const finderinfo = (uint32_t*)(block + 80);
+    void* const allocfile = (void*)(block + 112);
+    void* const extentsfile = (void*)(block + 192);
+    void* const catalogfile = (void*)(block + 272);
+    void* const attrsfile = (void*)(block + 352);
+    void* const startupfile = (void*)(block + 432);
+
+    sig[0] = 'H';
+    sig[1] = '+';
+    attrs[0] = HFS_ATTRIBUTES;
+    version[0] = 4;
+    lastmountvers[0] = 'f';
+    lastmountvers[1] = 's';
+    lastmountvers[2] = 'c';
+    lastmountvers[3] = 'k';
+    journalinfo[0] = HFS_RESERVED;
+    createdate[0] = currtime;
+    moddate[0] = currtime;
+    backupdate[0] = currtime;
+    checkdate[0] = currtime;
+    filecount[0] = 1;
+    foldercount[0] = 3;
+    blocksize[0] = HFS_BLOCK_SIZE;
+    rsrcclumpsize[0] = HFS_BLOCK_SIZE;
+    dataclumpsize[0] = HFS_BLOCK_SIZE;
+    writecount[0] = 1;
+    encodings[0] = HFS_RESERVED;
+    finderinfo[3] = 0;
+    finderinfo[4] = HFS_RESERVED;
+    finderinfo[6] = 0;
+    finderinfo[7] = 0;
+    init_null_fork_data(extentsfile);
+    init_null_fork_data(attrsfile);
+
+    const int count = fwrite(block, 1, HFS_BLOCK_SIZE, file);
+
+    return count == HFS_BLOCK_SIZE ? 0 : -1;
+
+  }
+
+  else
+    return errno;
+
+}
+
+#define HEADER_REC_OFFSET 14
+#define HEADER_USER_OFFSET 120
+#define HEADER_MAP_OFFSET 248
+
+static int write_catalog_header_node(FILE* const restrict file) {
+
+  uint32_t* const flink = (uint32_t*)node;
+  uint32_t* const blink = (uint32_t*)(node + 4);
+  int8_t* const kind = (int8_t*)(node + 8);
+  uint8_t* const height = node + 9;
+  uint16_t* const records = (uint16_t*)(node + 10);
+  uint16_t* const reserved = (uint16_t*)(node + 12);
+  uint16_t* const treedepth = (uint16_t*)(node + 14);
+  uint32_t* const rootnode = (uint32_t*)(node + 16);
+  uint32_t* const leafrecords = (uint32_t*)(node + 20);
+  uint32_t* const firstleaf = (uint32_t*)(node + 24);
+  uint32_t* const lastleaf = (uint32_t*)(node + 28);
+  uint16_t* const nodesize = (uint16_t*)(node + 32);
+  uint16_t* const maxkeylen = (uint16_t*)(node + 34);
+  uint32_t* const totalnodes = (uint32_t*)(node + 36);
+  uint32_t* const freenodes = (uint32_t*)(node + 40);
+  uint16_t* const reserved2 = (uint16_t*)(node + 44);
+  uint32_t* const clumpsize = (uint32_t*)(node + 46);
+  uint8_t* const btreetype = node + 50;
+  uint8_t* const keycomptype = node + 51;
+  uint32_t* const attrs = (uint32_t*)(node + 52);
+  uint32_t* const reserved3 = (uint32_t*)(node + 56);
+  uint16_t* const freeoff = (uint16_t*)(node + 8184);
+  uint16_t* const mapoff = (uint16_t*)(node + 8186);
+  uint16_t* const useroff = (uint16_t*)(node + 8188);
+  uint16_t* const headerrecoff = (uint16_t*)(node + 8190);
+
+  memset(node, 0, HFS_CATALOG_NODE_SIZE);
+  flink[0] = 0;
+  blink[0] = 0;
+  height[0] = 0;
+  records[0] = 3;
+  reserved[0] = HFS_RESERVED;
+  treedepth[0] = 0;
+  nodesize[0] = HFS_CATALOG_NODE_SIZE;
+  reserved2[0] = HFS_RESERVED;
+  clumpsize[0] = HFS_CATALOG_NODE_SIZE;
+  btreetype[0] = 0;
+  keycomptype[0] = 0xbc;
+  attrs[0] = 4;
+  reserved3[0] = HFS_RESERVED;
+  reserved3[1] = HFS_RESERVED;
+  reserved3[2] = HFS_RESERVED;
+  freeoff[0] = 8176;
+  mapoff[0] = HEADER_MAP_OFFSET;
+  useroff[0] = HEADER_USER_OFFSET;
+  headerrecoff[0] = HEADER_REC_OFFSET;
+
+  return fwrite(node, 1, HFS_CATALOG_NODE_SIZE, file);
+
+}
+
+static int write_catalog_data_node(FILE* const restrict file) {
+
+  uint32_t* const flink = (uint32_t*)node;
+  uint32_t* const blink = (uint32_t*)(node + 4);
+  int8_t* const kind = (int8_t*)(node + 8);
+  uint8_t* const height = node + 9;
+  uint16_t* const records = (uint16_t*)(node + 10);
+  uint16_t* const reserved = (uint16_t*)(node + 12);
+  uint16_t* const systemdiroff = (uint16_t*)(node + 8188);
+  uint16_t* const rootdiroff = (uint16_t*)(node + 8190);
+
+  flink[0] = 0;
+  blink[0] = 0;
+  kind[0] = -1;
+  height[0] = 1;
+  records[0] = 7;
+  rootdiroff[0] = 14;
+
+  return fwrite(node, 1, HFS_CATALOG_NODE_SIZE, file);
+
+}
+
+static int write_hfs_epilog(FILE* restrict const file) {
+
+  return fwrite(zeroes, HFS_EPILOG_SIZE, 1, file);
+
+}
+
+int write_hfs_image(FILE* const restrict infile,
+		    FILE* const restrict outfile) {
+
+  int out;
+
+  if((out = fseek(infile, 0, SEEK_SET)))
+    return out;
+
+  if((out = fseek(outfile, 0, SEEK_SET)))
+    return out;
+
+  if((out = write_hfs_prolog(outfile))) {
+    perror("Could not write prologue");
+    return out;
+  }
+
+  if((out = write_hfs_volume_header(outfile))) {
+    perror("Could not write volume header");
+    return out;
+  }
+
+  return out;
+
+}

Added: soc2012/emc2/hfsimg/hfsimg.8
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2012/emc2/hfsimg/hfsimg.8	Mon Jun  4 18:40:08 2012	(r237076)
@@ -0,0 +1,20 @@
+.Dd June 4, 2012
+.Dt HFSIMG 8
+.Os
+.Sh NAME
+.Nm hfsimg
+.Nd "embed a boot loader within an HFS+ filesystem image"
+.Sh SYNOPSIS
+.Nm
+image volume
+.Sh DESCRIPTION
+The hfsimg utility creates an HFS+ filesystem image containing a single file as
+a boot loader program on the given volume.  The filesystem will contain a single
+file, named boot.efi in the /System/Library/CoreServices directory, which will
+be marked as a startup file in the filesystem.  The contents of this file will
+be exactly the contents of the image file given to hfsimg.
+
+This is intended for installing boot loaders on Apple machines, which have
+an alternate boot procedure from the UEFI specification.
+.Sh AUTHORS
+.An Eric McCorkle

Added: soc2012/emc2/hfsimg/main.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2012/emc2/hfsimg/main.c	Mon Jun  4 18:40:08 2012	(r237076)
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+#include "hfs.h"
+
+int main(int argc, char** argv) {
+
+  int out;
+  FILE* infile;
+  FILE* outfile;
+
+  if(3 != argc)
+    fprintf(stderr, "Usage: %s <boot image> <volume>\n", argv[0]);
+
+  if(!(infile = fopen(argv[1], "r"))) {
+    perror("Could not open input file");
+    return out;
+  }
+
+  if(!(outfile = fopen(argv[2], "w"))) {
+    perror("Could not open output file");
+    return out;
+  }
+
+  return write_hfs_image(infile, outfile);
+
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120604184008.EC1AB106564A>