root/sys/arch/macppc/stand/mkboothfs/mkboothfs.c
/*      $NetBSD: mkboothfs.c,v 1.1 2024/09/15 03:56:58 tsutsui Exp $    */

/*-
 * Copyright (c) 2005, 2006 Izumi Tsutsui.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#include "../../sys/sys/bootblock.h"
#else
#include <sys/bootblock.h>
#endif
#if !HAVE_NBTOOL_CONFIG_H || HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#endif

#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

#define BUFSIZE         (64 * 1024)

#define BSIZE           512
#define BOOTPARTSIZE    32768   /* XXX: not sure how much required */
#define BOOTDATASIZE    (BOOTPARTSIZE - MACPPC_BOOT_BLOCK_MAX_SIZE)

#define HFS_BLKSIZE     512
#define HFS_MAGICOFFSET (BOOTDATASIZE - (HFS_BLKSIZE * 2))
#define HFS_MAGIC       0x4c4b

#define SIZETOBLK512(size)      ((size) / 512)
#define SIZETOBLK2048(size)     ((size) / 2048)

static void usage(void);

/*
 * Creates a file for use by mkisofs's -boot-hfs-file.
 */

int
main(int argc, char **argv)
{
        char *boothfs;
        int ofd;
        struct apple_drvr_map dm;
        struct apple_part_map_entry pme;
        char *buf;

        if (argc != 2)
                usage();

        boothfs = argv[1];

        buf = malloc(BUFSIZE);
        if (buf == NULL)
                err(1, "malloc write buffer");

        /* create output boot-hfs-file */
        if ((ofd = open(boothfs, O_CREAT | O_TRUNC | O_WRONLY, 0644)) == -1)
                err(1, "create output boot-hfs-file `%s'", boothfs);
        
        /*
         * Populate 18 byte driver map header in the first 512 byte block
         */
        memset(&dm, 0, sizeof dm);
        dm.sbSig = htobe16(APPLE_DRVR_MAP_MAGIC);
        dm.sbBlockSize = htobe16(2048);
        dm.sbBlkCount = htobe32(0);     /* XXX */
        dm.sbDevType = htobe16(1);
        dm.sbDevID = htobe16(1);
        dm.sbData = 0;
        dm.sbDrvrCount = 0;

        memset(buf, 0, BSIZE);
        memcpy(buf, &dm, sizeof(dm));
        write(ofd, buf, BSIZE);

        /*
         * Write 2048-byte/sector map in the second 512 byte block
         */
        memset(&pme, 0, sizeof(pme));
        pme.pmSig =             htobe16(APPLE_PART_MAP_ENTRY_MAGIC);
        pme.pmMapBlkCnt =       htobe32(1);
        pme.pmPyPartStart =     htobe32(1);
        pme.pmPartBlkCnt =      htobe32(SIZETOBLK2048(BOOTPARTSIZE));
        pme.pmDataCnt =         htobe32(SIZETOBLK2048(BOOTDATASIZE));
        strlcpy(pme.pmPartName, "NetBSD_BootBlock", sizeof(pme.pmPartName));
        strlcpy(pme.pmPartType, "Apple_Driver", sizeof(pme.pmPartType));
        pme.pmPartStatus =      htobe32(0x3b);
        pme.pmBootSize =        htobe32(MACPPC_BOOT_BLOCK_MAX_SIZE);
        pme.pmBootLoad =        htobe32(0x4000);
        pme.pmBootEntry =       htobe32(0x4000);
        strlcpy(pme.pmProcessor, "PowerPC", sizeof(pme.pmProcessor));

        memset(buf, 0, BSIZE);
        memcpy(buf, &pme, sizeof(pme));
        write(ofd, buf, BSIZE);

        /*
         * Write 512-byte/sector map in the third 512 byte block
         */
        pme.pmPyPartStart =     htobe32(4);
        pme.pmPartBlkCnt =      htobe32(SIZETOBLK512(BOOTPARTSIZE));
        pme.pmDataCnt =         htobe32(SIZETOBLK512(BOOTDATASIZE));
        memset(buf, 0, BSIZE);
        memcpy(buf, &pme, sizeof(pme));
        write(ofd, buf, BSIZE);

        /*
         * Placeholder for 2048 byte padding
         */
        memset(buf, 0, BSIZE);
        write(ofd, buf, BSIZE);

        /*
         * Placeholder for NetBSD bootblock
         */
        memset(buf, 0, MACPPC_BOOT_BLOCK_MAX_SIZE);
        write(ofd, buf, MACPPC_BOOT_BLOCK_MAX_SIZE);

        /*
         * Prepare HFS "bootblock"; enough to pacify mkisofs.
         */
        memset(buf, 0, BOOTDATASIZE);
        be16enc(&buf[HFS_MAGICOFFSET], HFS_MAGIC);
        if (write(ofd, buf, BOOTDATASIZE) != BOOTDATASIZE)
                err(1, "write boot-hfs-file `%s'", boothfs);
 
        free(buf);
        close(ofd);
        return 0;
}

static void
usage(void)
{
        const char *prog;

        prog = getprogname();
        fprintf(stderr, "usage: %s boot-hfs-file\n", prog);
        exit(1);
}