socsvn commit: r237076 - soc2012/emc2/hfsimg
emc2 at FreeBSD.org
emc2 at FreeBSD.org
Mon Jun 4 18:40:11 UTC 2012
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);
+
+}
More information about the svn-soc-all
mailing list