mirror of
https://github.com/vivier/EMILE.git
synced 2025-01-28 08:32:38 +00:00
081c7f96ee
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
283 lines
7.6 KiB
C
283 lines
7.6 KiB
C
/*
|
|
*
|
|
* (c) 2015 Laurent Vivier <Laurent@Vivier.EU>
|
|
*
|
|
* HOWTO create a bootable disk:
|
|
*
|
|
* emile-mktable -e second/m68k-linux-scsi-driver/apple_driver /dev/sdh
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <getopt.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <libgen.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/mount.h>
|
|
|
|
#include <libmap.h>
|
|
#include <emile.h>
|
|
#include <libemile.h>
|
|
#include <libiso9660.h>
|
|
#include <libstream.h>
|
|
|
|
#include "device.h"
|
|
|
|
#define DRIVER_SIZE (64*1024)
|
|
|
|
#define DRIVER_PATH "/lib/emile/apple_driver"
|
|
|
|
#define PARTITION_TABLE_LEN 63
|
|
#define DRIVER_BASE (PARTITION_TABLE_LEN + 1)
|
|
#define MAP_BLOCK_COUNT 4 /* 4 entries in the table: map, driver, HFS, extra */
|
|
#define EXTRA_BASE (4*1024*1024/512) /* 4 MB */
|
|
|
|
enum {
|
|
ARG_NONE = 0,
|
|
ARG_HELP ='h',
|
|
ARG_EMILEDRIVER = 'e',
|
|
};
|
|
|
|
static struct option long_options[] =
|
|
{
|
|
{"help", 0, NULL, ARG_HELP },
|
|
{"emiledriver", 1, NULL, ARG_EMILEDRIVER },
|
|
{NULL, 0, NULL, 0 },
|
|
};
|
|
|
|
static void usage(int argc, char** argv)
|
|
{
|
|
fprintf(stderr, "Usage %s [FLAGS] disk\n",
|
|
argv[0]);
|
|
fprintf(stderr, "Create and EMILE bootable disk\n");
|
|
fprintf(stderr, " -h, --help display this text\n");
|
|
fprintf(stderr, " -e, --emiledriver=FILE "
|
|
"emiledriver to copy to disk\n");
|
|
fprintf(stderr, "\nbuild: \n%s\n", SIGNATURE);
|
|
}
|
|
|
|
#define BLOCKSIZE (512)
|
|
|
|
static int emile_mktable(char *filename, char *appledriver)
|
|
{
|
|
struct DriverDescriptor block0;
|
|
struct Partition *map512;
|
|
int fd_driver;
|
|
unsigned char *driver;
|
|
struct stat st;
|
|
int driver_size;
|
|
int fd;
|
|
int i;
|
|
unsigned long disk_block_count;
|
|
u_int32_t driver_block_count, extra_block_count, hfs_block_count;
|
|
int current;
|
|
|
|
/* open disk */
|
|
|
|
fd = open(filename, O_WRONLY);
|
|
if (fd == -1) {
|
|
fprintf(stderr,
|
|
"ERROR: Cannot open file %s\n",
|
|
filename);
|
|
return -1;
|
|
}
|
|
if (ioctl(fd, BLKGETSIZE, &disk_block_count) == -1) {
|
|
fstat(fd, &st);
|
|
disk_block_count = (st.st_size + 512 - 1) / 512;
|
|
}
|
|
|
|
/* read apple driver */
|
|
|
|
fd_driver = open(appledriver, O_RDONLY);
|
|
if (fd_driver == -1)
|
|
{
|
|
fprintf(stderr, "Cannot open %s\n", appledriver);
|
|
return -1;
|
|
}
|
|
fstat(fd_driver, &st);
|
|
driver_size = ((st.st_size + DRIVER_SIZE - 1) / DRIVER_SIZE) *
|
|
DRIVER_SIZE;
|
|
driver = malloc(driver_size);
|
|
memset(driver, 0, driver_size);
|
|
if (driver == NULL)
|
|
{
|
|
fprintf(stderr, "Cannot malloc %d bytes\n", driver_size);
|
|
return -1;
|
|
}
|
|
read(fd_driver, driver, st.st_size);
|
|
|
|
close(fd_driver);
|
|
|
|
/* Driver Descriptor 512 bytes
|
|
* Driver Partition Map (for 512 byte blocks) 512 bytes
|
|
* Driver Partition N x 512 bytes
|
|
* HFS
|
|
* Extra
|
|
*/
|
|
|
|
|
|
/* initialize block 0 with the size of the disk and the number of driver */
|
|
|
|
memset(&block0, 0, sizeof(block0));
|
|
write_short((u_int16_t*)&block0.Sig, DD_SIGNATURE);
|
|
write_short((u_int16_t*)&block0.BlkSize, BLOCKSIZE);
|
|
write_long((u_int32_t*)&block0.BlkCount, disk_block_count);
|
|
write_short((u_int16_t*)&block0.DevType, 1);
|
|
write_short((u_int16_t*)&block0.DevId, 1);
|
|
write_long((u_int32_t*)&block0.Data, 0);
|
|
write_short((u_int16_t*)&block0.DrvrCount, 1);
|
|
|
|
/* initialize driver info */
|
|
|
|
write_long((u_int32_t*)&block0.DrvInfo[0].Block, DRIVER_BASE);
|
|
write_short((u_int16_t*)&block0.DrvInfo[0].Size, (driver_size + BLOCKSIZE - 1) / BLOCKSIZE);
|
|
write_short((u_int16_t*)&block0.DrvInfo[0].Type, kDriverTypeMacSCSI);
|
|
|
|
/* initialize partition table */
|
|
|
|
map512 = malloc(PARTITION_TABLE_LEN * 512);
|
|
if (map512 == NULL)
|
|
{
|
|
fprintf(stderr, "Cannot malloc %d bytes\n",
|
|
PARTITION_TABLE_LEN * 512);
|
|
return -1;
|
|
}
|
|
|
|
memset(map512, 0, PARTITION_TABLE_LEN * 512);
|
|
current = 0;
|
|
|
|
/* partition table entry */
|
|
|
|
write_short((u_int16_t*)&map512[current].Sig, MAP_SIGNATURE);
|
|
write_long((u_int32_t*)&map512[current].MapBlkCnt, MAP_BLOCK_COUNT);
|
|
write_long((u_int32_t*)&map512[current].PyPartStart, 1);
|
|
write_long((u_int32_t*)&map512[current].PartBlkCnt, PARTITION_TABLE_LEN);
|
|
strncpy(map512[current].PartName, "Apple", 32);
|
|
strncpy(map512[current].PartType, APPLE_PARTITION_MAP, 32);
|
|
write_long((u_int32_t*)&map512[current].DataCnt, PARTITION_TABLE_LEN);
|
|
write_long((u_int32_t*)&map512[current].PartStatus,
|
|
kPartitionAUXIsWriteable | kPartitionAUXIsReadable |
|
|
kPartitionAUXIsInUse | kPartitionAUXIsAllocated |
|
|
kPartitionAUXIsValid );
|
|
current++;
|
|
|
|
/* initialize driver partition entry */
|
|
|
|
driver_block_count = (driver_size + 512 - 1) / 512;
|
|
write_short((u_int16_t*)&map512[current].Sig, MAP_SIGNATURE);
|
|
write_long((u_int32_t*)&map512[current].MapBlkCnt, MAP_BLOCK_COUNT);
|
|
write_long((u_int32_t*)&map512[current].PartBlkCnt, driver_block_count);
|
|
write_long((u_int32_t*)&map512[current].PyPartStart, DRIVER_BASE);
|
|
strncpy(map512[current].PartName, "Macintosh", 32);
|
|
strncpy(map512[current].PartType, APPLE_DRIVER_EMILE, 32);
|
|
write_long((u_int32_t*)&map512[current].DataCnt, driver_block_count);
|
|
write_long((u_int32_t*)&map512[current].PartStatus, kPartitionAUXIsValid |
|
|
kPartitionAUXIsAllocated |
|
|
kPartitionAUXIsInUse |
|
|
kPartitionAUXIsBootValid |
|
|
kPartitionAUXIsReadable |
|
|
kPartitionAUXIsWriteable |
|
|
kPartitionAUXIsBootCodePositionIndependent |
|
|
kPartitionIsChainCompatible |
|
|
kPartitionIsRealDeviceDriver);
|
|
write_long((u_int32_t*)&map512[current].BootSize, st.st_size);
|
|
write_long((u_int32_t*)&map512[current].BootCksum, map_checksum(driver, st.st_size));
|
|
strncpy(map512[current].Processor, "68000", 16);
|
|
write_long((u_int32_t*)&map512[current].Pad, kSCSIDriverSignature);
|
|
current++;
|
|
|
|
/* HFS table entry */
|
|
|
|
hfs_block_count = EXTRA_BASE - (DRIVER_BASE + driver_block_count);
|
|
write_short((u_int16_t*)&map512[current].Sig, MAP_SIGNATURE);
|
|
write_long((u_int32_t*)&map512[current].MapBlkCnt, MAP_BLOCK_COUNT);
|
|
write_long((u_int32_t*)&map512[current].PyPartStart, DRIVER_BASE + driver_block_count);
|
|
write_long((u_int32_t*)&map512[current].PartBlkCnt, hfs_block_count);
|
|
strncpy(map512[current].PartName, "MacOS", 32);
|
|
strncpy(map512[current].PartType, APPLE_HFS, 32);
|
|
write_long((u_int32_t*)&map512[current].DataCnt, hfs_block_count);
|
|
current++;
|
|
|
|
/* extra (free) table entry */
|
|
|
|
extra_block_count = disk_block_count - EXTRA_BASE;
|
|
write_short((u_int16_t*)&map512[current].Sig, MAP_SIGNATURE);
|
|
write_long((u_int32_t*)&map512[current].MapBlkCnt, MAP_BLOCK_COUNT);
|
|
write_long((u_int32_t*)&map512[current].PyPartStart, EXTRA_BASE);
|
|
write_long((u_int32_t*)&map512[current].PartBlkCnt, extra_block_count);
|
|
strncpy(map512[current].PartName, "Extra", 32);
|
|
strncpy(map512[current].PartType, APPLE_FREE, 32);
|
|
write_long((u_int32_t*)&map512[current].DataCnt, extra_block_count);
|
|
current++;
|
|
|
|
/* write block 0*/
|
|
|
|
write(fd, &block0, sizeof(block0));
|
|
|
|
/* write partition table */
|
|
|
|
for (i = 0; i < PARTITION_TABLE_LEN; i++)
|
|
{
|
|
write(fd, map512 + i, 512);
|
|
}
|
|
|
|
/* write driver */
|
|
|
|
write(fd, driver, driver_size);
|
|
free(driver);
|
|
|
|
close(fd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
int option_index = 0;
|
|
char* image = NULL;
|
|
char* emiledriver = NULL;
|
|
int c;
|
|
|
|
while(1)
|
|
{
|
|
c = getopt_long(argc, argv, "he:c:",
|
|
long_options, &option_index);
|
|
if (c == -1)
|
|
break;
|
|
switch(c)
|
|
{
|
|
case ARG_HELP:
|
|
usage(argc, argv);
|
|
return 0;
|
|
case ARG_EMILEDRIVER:
|
|
emiledriver = optarg;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (optind < argc)
|
|
image = argv[optind++];
|
|
|
|
if (image == NULL)
|
|
{
|
|
fprintf(stderr,"ERROR: you must provide a filename to write image\n");
|
|
usage(argc, argv);
|
|
return 1;
|
|
}
|
|
|
|
if (emiledriver == NULL)
|
|
emiledriver = DRIVER_PATH;
|
|
|
|
|
|
if (emile_mktable(image, emiledriver))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|