From 1485d7a2d7e9d2af5c68965b3f35671448c5e337 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 15 Jul 2007 00:04:27 +0000 Subject: [PATCH] Added small tool source_to_data, which takes an arbitrary data file and generates a C source file defining an array variable containing the file's data. DataFileToSourceFile is the respective jam rule. The idea is to directly built the boot archive into the boot loader for network booting (and thus avoiding to download it from somewhere). In case of PXE this doesn't work, though, due to restrictions to the size of the NBP. Maybe Open Firmware is less restrictive. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21602 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- build/jam/FileRules | 20 ++++++ src/tools/Jamfile | 3 + src/tools/data_to_source.cpp | 119 +++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 src/tools/data_to_source.cpp diff --git a/build/jam/FileRules b/build/jam/FileRules index 0ec5966692..292485b3dd 100644 --- a/build/jam/FileRules +++ b/build/jam/FileRules @@ -253,3 +253,23 @@ actions CopySetHaikuRevision1 $(2[2]) $(1) ${revision} } +rule DataFileToSourceFile sourceFile : dataFile : dataVariable : sizeVariable +{ + sourceFile = [ FGristFiles $(sourceFile) ] ; + MakeLocateCommonPlatform $(sourceFile) ; + + sizeVariable ?= $(dataVariable)Size ; + + DATA_VARIABLE on $(sourceFile) = $(dataVariable) ; + SIZE_VARIABLE on $(sourceFile) = $(sizeVariable) ; + + Depends $(sourceFile) : data_to_source $(dataFile) ; + DataFileToSourceFile1 $(sourceFile) : data_to_source $(dataFile) ; + LocalClean clean : $(sourceFile) ; +} + +actions DataFileToSourceFile1 +{ + $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) + $(2[1]) $(DATA_VARIABLE) $(SIZE_VARIABLE) $(2[2]) $(1) +} diff --git a/src/tools/Jamfile b/src/tools/Jamfile index 029d4bfc15..d61420d287 100644 --- a/src/tools/Jamfile +++ b/src/tools/Jamfile @@ -30,6 +30,9 @@ BuildPlatformMain catattr : catattr.cpp : $(HOST_LIBBE) ; BuildPlatformMain copyattr : copyattr.cpp : $(HOST_LIBBE) $(HOST_LIBSTDC++) $(HOST_LIBSUPC++) ; +BuildPlatformMain data_to_source : data_to_source.cpp + : $(HOST_LIBSUPC++) ; + BuildPlatformMain listattr : listattr.cpp : $(HOST_LIBBE) ; if $(HOST_PLATFORM_BEOS_COMPATIBLE) { diff --git a/src/tools/data_to_source.cpp b/src/tools/data_to_source.cpp new file mode 100644 index 0000000000..adf5c51d28 --- /dev/null +++ b/src/tools/data_to_source.cpp @@ -0,0 +1,119 @@ +/* + * Copyright 2007, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include +#include +#include +#include +#include +#include + + +void +write_string(int fd, const char* data) +{ + int len = strlen(data); + if (len == 0) + return; + + ssize_t written = write(fd, data, len); + if (written < 0) { + fprintf(stderr, "Error: Failed to write to output file: %s\n", + strerror(errno)); + exit(1); + } +} + + +int +main(int argc, const char* const* argv) +{ + if (argc != 5) { + fprintf(stderr, + "Usage: %s \n", + argv[0]); + exit(1); + } + const char* dataVarName = argv[1]; + const char* sizeVarName = argv[2]; + const char* inFileName = argv[3]; + const char* outFileName = argv[4]; + + // open files + int inFD = open(inFileName, O_RDONLY); + if (inFD < 0) { + fprintf(stderr, "Error: Failed to open input file \"%s\": %s\n", + inFileName, strerror(errno)); + exit(1); + } + + int outFD = open(outFileName, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (outFD < 0) { + fprintf(stderr, "Error: Failed to open output file \"%s\": %s\n", + outFileName, strerror(errno)); + exit(1); + } + + const int kCharsPerLine = 15; + const int kBufferSize = 16 * 1024; + unsigned char buffer[kBufferSize]; + char lineBuffer[128]; + + sprintf(lineBuffer, "unsigned char %s[] = {\n", dataVarName); + write_string(outFD, lineBuffer); + + off_t dataSize = 0; + off_t offset = 0; + char* lineBufferEnd = lineBuffer; + *lineBufferEnd = '\0'; + while (true) { + // read a buffer + ssize_t bytesRead = read(inFD, buffer, kBufferSize); + if (bytesRead < 0) { + fprintf(stderr, "Error: Failed to read from input file: %s\n", + strerror(errno)); + exit(1); + } + if (bytesRead == 0) + break; + + dataSize += bytesRead; + + // write lines + for (int i = 0; i < bytesRead; i++, offset++) { + if (offset % kCharsPerLine == 0) { + if (offset > 0) { + // line is full -- flush it + strcpy(lineBufferEnd, ",\n"); + write_string(outFD, lineBuffer); + lineBufferEnd = lineBuffer; + *lineBufferEnd = '\0'; + } + + sprintf(lineBufferEnd, "\t%u", (unsigned)buffer[i]); + } else + sprintf(lineBufferEnd, ", %u", (unsigned)buffer[i]); + + lineBufferEnd += strlen(lineBufferEnd); + } + } + + // flush the line buffer + if (lineBufferEnd != lineBuffer) { + strcpy(lineBufferEnd, ",\n"); + write_string(outFD, lineBuffer); + } + + // close the braces and write the size variable + sprintf(lineBuffer, "};\nlong long %s = %lldLL;\n", sizeVarName, + dataSize); + write_string(outFD, lineBuffer); + + close(inFD); + close(outFD); + + return 0; +}