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>