Adding an "anyboot" buildtool that takes a chainloading MBR, a ISO CD boot image
and a Haiku image and fuses everything to a hybrid MBR/ISO image. Since it contains a valid MBR, partition table and el-torito CD boot record such an image should be pretty universally bootable. It can be written to disks, USB sticks or CDs/DVDs. Since it has a partition table in place it is also possible that it helps with the non-booting USB sticks where the BIOS (wrongly) assumes a partition table. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35667 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
36e9797f23
commit
bfa5a8db18
@ -103,6 +103,7 @@ SEARCH on [ FGristFiles
|
||||
] = [ FDirName $(HAIKU_TOP) src kits shared ] ;
|
||||
|
||||
SubInclude HAIKU_TOP src tools addattr ;
|
||||
SubInclude HAIKU_TOP src tools anyboot ;
|
||||
SubInclude HAIKU_TOP src tools bfs_shell ;
|
||||
SubInclude HAIKU_TOP src tools cppunit ;
|
||||
SubInclude HAIKU_TOP src tools docbook ;
|
||||
|
3
src/tools/anyboot/Jamfile
Normal file
3
src/tools/anyboot/Jamfile
Normal file
@ -0,0 +1,3 @@
|
||||
SubDir HAIKU_TOP src tools anyboot ;
|
||||
|
||||
BuildPlatformMain <build>anyboot : anyboot.cpp : ;
|
123
src/tools/anyboot/anyboot.cpp
Normal file
123
src/tools/anyboot/anyboot.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static uint8_t *sCopyBuffer = NULL;
|
||||
static size_t sCopyBufferSize = 2 * 1024 * 1024;
|
||||
|
||||
|
||||
int
|
||||
copyLoop(int from, int to, off_t position)
|
||||
{
|
||||
while (true) {
|
||||
ssize_t copyLength = read(from, sCopyBuffer, sCopyBufferSize);
|
||||
if (copyLength <= 0)
|
||||
return copyLength;
|
||||
|
||||
ssize_t written = write_pos(to, position, sCopyBuffer, copyLength);
|
||||
if (written != copyLength) {
|
||||
if (written < 0)
|
||||
return written;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
position += copyLength;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
checkError(bool failed, const char *message)
|
||||
{
|
||||
if (!failed)
|
||||
return;
|
||||
|
||||
printf("%s: %s\n", message, strerror(errno));
|
||||
free(sCopyBuffer);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 5) {
|
||||
printf("usage: %s <outputFile> <isoFile> <mbrFile> <imageFile>\n",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sCopyBuffer = (uint8_t *)malloc(sCopyBufferSize);
|
||||
checkError(sCopyBuffer == NULL, "no memory for copy buffer");
|
||||
|
||||
static const size_t kBlockSize = 512;
|
||||
|
||||
int outputFile = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT);
|
||||
checkError(outputFile < 0, "failed to open output file");
|
||||
|
||||
int isoFile = open(argv[2], O_RDONLY);
|
||||
checkError(isoFile < 0, "failed to open ISO file");
|
||||
|
||||
struct stat stat;
|
||||
int result = fstat(isoFile, &stat);
|
||||
checkError(result != 0, "failed to stat ISO file");
|
||||
off_t isoSize = stat.st_size;
|
||||
|
||||
int mbrFile = open(argv[3], O_RDONLY);
|
||||
checkError(mbrFile < 0, "failed to open MBR file");
|
||||
|
||||
int imageFile = open(argv[4], O_RDONLY);
|
||||
checkError(imageFile < 0, "failed to open image file");
|
||||
|
||||
result = fstat(imageFile, &stat);
|
||||
checkError(result != 0, "failed to stat image file");
|
||||
|
||||
off_t imageSize = stat.st_size;
|
||||
|
||||
result = copyLoop(isoFile, outputFile, 0);
|
||||
checkError(result != 0, "failed to copy iso file to output");
|
||||
|
||||
// isoSize rounded to the next full megabyte
|
||||
off_t alignment = 1 * 1024 * 1024 - 1;
|
||||
off_t imageOffset = (isoSize + alignment) & ~alignment;
|
||||
|
||||
result = copyLoop(imageFile, outputFile, imageOffset);
|
||||
checkError(result != 0, "failed to copy image file to output");
|
||||
|
||||
result = copyLoop(mbrFile, outputFile, 0);
|
||||
checkError(result != 0, "failed to copy mbr to output");
|
||||
|
||||
// construct the partition table
|
||||
uint8_t partition[16] = {
|
||||
0x80, // active
|
||||
0xff, 0xff, 0xff, // CHS start offset
|
||||
// TODO: we enforce LBA here, maybe not a good idea?
|
||||
0xeb, // partition type (BFS)
|
||||
0xff, 0xff, 0xff, // CHS end offset
|
||||
// TODO: see above
|
||||
0x00, 0x00, 0x00, 0x00, // imageOffset in blocks (written below)
|
||||
0x00, 0x00, 0x00, 0x00 // imageSize in blocks (written below)
|
||||
};
|
||||
|
||||
alignment = kBlockSize - 1;
|
||||
imageSize = (imageSize + alignment) & ~alignment;
|
||||
|
||||
uint32_t partitionOffset = (uint32_t)(imageOffset / kBlockSize);
|
||||
((uint32_t *)partition)[2] = partitionOffset;
|
||||
((uint32_t *)partition)[3] = (uint32_t)(imageSize / kBlockSize);
|
||||
ssize_t written = write_pos(outputFile, 512 - 2 - 16 * 4, partition, 16);
|
||||
checkError(written != 16, "failed to write partition entry");
|
||||
|
||||
// and make the image bootable
|
||||
written = write_pos(outputFile, imageOffset + 512 - 2 - 4,
|
||||
&partitionOffset, 4);
|
||||
checkError(written != 4, "failed to make image bootable");
|
||||
|
||||
free(sCopyBuffer);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user