diff --git a/tools/emile-install.c b/tools/emile-install.c new file mode 100644 index 0000000..a93b35e --- /dev/null +++ b/tools/emile-install.c @@ -0,0 +1,409 @@ +/* + * + * (c) 2004 Laurent Vivier + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "emile.h" +#include "emile-first.h" +#include "emile-second.h" + +static void usage(int argc, char** argv) +{ + fprintf(stderr, "Usage: %s -f -s -i -r -b \n", argv[0]); +} + +static unsigned long get_size(char* file) +{ + struct stat result; + + stat(file, &result); + + return (result.st_size + SECTOR_SIZE - 1) / SECTOR_SIZE * SECTOR_SIZE; +} + +static int second_tune(int fd, char* second_level, char *kernel_image, unsigned buffer_size, char* ramdisk) +{ + emile_l2_header_t header; + int ret; + + ret = lseek(fd, FIRST_LEVEL_SIZE, SEEK_SET); + if (ret == -1) + { + close(fd); + return 3; + } + + ret = read(fd, &header, sizeof(header)); + if (ret != sizeof(header)) + { + close(fd); + return 7; + } + + write_long(&header.kernel_image_offset, + FIRST_LEVEL_SIZE + get_size(second_level)); + write_long(&header.kernel_image_size, + get_size(kernel_image)); + write_long(&header.kernel_size, buffer_size); + + if (ramdisk == NULL) + { + write_long(&header.ramdisk_offset, 0); + write_long(&header.ramdisk_size, 0); + } + else + { + write_long(&header.ramdisk_offset, + read_long(&header.kernel_image_offset) + + read_long(&header.kernel_image_size)); + write_long(&header.ramdisk_size, get_size(ramdisk)); + } + printf("Setting second level info: \n"); + printf("kernel offset %ld, kernel size %ld, buffer size %ld\n", + read_long(&header.kernel_image_offset), + read_long(&header.kernel_image_size), + read_long(&header.kernel_size)); + printf("ramdisk offset %ld, ramdisk size %ld\n", + read_long(&header.ramdisk_offset), + read_long(&header.ramdisk_size)); + + ret = lseek(fd, FIRST_LEVEL_SIZE, SEEK_SET); + if (ret == -1) + { + close(fd); + return 3; + } + + ret = write(fd, &header, sizeof(header)); + if (ret != sizeof(header)) + { + close(fd); + return 7; + } + + return 0; +} + +static int first_tune(int fd, char* second_level) +{ + int ret; + eBootBlock_t firstBlock; + + ret = lseek(fd, 0, SEEK_SET); + if (ret == -1) + return 9; + + ret = read(fd, &firstBlock, sizeof(firstBlock)); + if (ret != sizeof(firstBlock)) + return 10; + + /* drive number */ + + write_short(&firstBlock.second_param_block.ioVRefNum, 1); + + /* second offset */ + + write_long(&firstBlock.second_param_block.ioPosOffset, FIRST_LEVEL_SIZE); + + /* second size */ + + write_long(&firstBlock.second_param_block.ioReqCount, get_size(second_level)); + + printf( + "Setting second level position to: drive %d, offset %ld, size %ld\n", + read_short(&firstBlock.second_param_block.ioVRefNum), + read_long(&firstBlock.second_param_block.ioPosOffset), + read_long(&firstBlock.second_param_block.ioReqCount)); + + /* writing */ + + ret = lseek(fd, 0, SEEK_SET); + if (ret == -1) + return 11; + + ret = write(fd, &firstBlock, sizeof(firstBlock)); + if (ret != sizeof(firstBlock)) + if (ret != sizeof(firstBlock)) + return 12; + + return 0; +} + +static int copy_file(int fd, char* file) +{ + int source; + int size_read; + int size_written; + int total; + static char buffer[SECTOR_SIZE]; + + if (fd < 0) + return 7; + + source = open(file, O_RDONLY); + if (source < 0) + { + close(source); + return 7; + } + + printf("Copying %s: ", file); + total = 0; + for(;;) + { + size_read = read(source, buffer, SECTOR_SIZE); + if (size_read == SECTOR_SIZE) + { + size_written = write(fd, buffer, SECTOR_SIZE); + total += size_written; + if (size_written != SECTOR_SIZE) + { + close(source); + return 8; + } + } + else + { + if (size_read == 0) + break; + + memset(buffer + size_read, 0, SECTOR_SIZE - size_read); + size_written = write(fd, buffer, SECTOR_SIZE); + total += size_written; + if (size_written != SECTOR_SIZE) + { + close(source); + return 8; + } + break; + } + } + + printf("%d bytes\n", total); + close(source); + return 0; +} + +static int aggregate(int fd, char* first_level, char* second_level, char* kernel_image, char* ramdisk) +{ + int ret; + + ret = copy_file(fd, first_level); + if (ret != 0) + return 6; + ret = copy_file(fd, second_level); + if (ret != 0) + return 6; + ret = copy_file(fd, kernel_image); + if (ret != 0) + return 6; + if (ramdisk != NULL) + { + ret = copy_file(fd, ramdisk); + if (ret != 0) + return 6; + } + + return 0; +} + +int create_image(char* first_level, char* second_level, char* kernel_image, + char* ramdisk, unsigned long buffer_size, char* image) +{ + int ret; + int fd; + + if (image == NULL) + { + fprintf(stderr, "Image file not defined\n"); + return 2; + } + + printf("Creating %s\n", image); + fd = open(image, O_RDWR|O_CREAT|O_TRUNC, + S_IRUSR| S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); + if (fd == -1) + { + perror("Cannot open image file"); + return 2; + } + + /* aggregating files: first, second, kernel, ramdisk */ + + if (first_level == NULL) + { + fprintf(stderr, "first level file not defined\n"); + close(fd); + return 3; + } + + if (second_level == NULL) + { + fprintf(stderr, "second level file not defined\n"); + close(fd); + return 4; + } + + if (kernel_image == NULL) + { + fprintf(stderr, "kernel image file not defined\n"); + close(fd); + return 5; + } + + ret = aggregate(fd, first_level, second_level, kernel_image, ramdisk); + if (ret != 0) + { + perror("Cannot create image\n"); + close(fd); + return 6; + } + + /* set first level info */ + + ret = first_tune(fd, second_level); + if (ret != 0) + { + close(fd); + return 7; + } + + /* set second level info */ + + ret = second_tune(fd, second_level, kernel_image, buffer_size, ramdisk); + if (ret != 0) + { + close(fd); + return 8; + } + + close(fd); + + return 0; +} + +int main(int argc, char** argv) +{ + char* first_level = NULL; + char* second_level = NULL; + char* kernel_image = NULL; + char* ramdisk = NULL; + unsigned long buffer_size = 0; + char* image = NULL; + int i; + int ret; + + if ((argc != 12) && (argc != 10)) + { + usage(argc, argv); + return 1; + } + + for (i = 1; i < argc; i++) + { + if (strcmp("-f", argv[i]) == 0) + { + if (first_level != NULL) + { + fprintf(stderr, "Duplicate definition of -f\n"); + return 1; + } + i++; + if (i < argc) + first_level = argv[i]; + else + { + fprintf(stderr, "Missing argument for -f\n"); + return 1; + } + } + else if (strcmp("-s", argv[i]) == 0) + { + if (second_level != NULL) + { + fprintf(stderr, "Duplicate definition of -s\n"); + return 1; + } + i++; + if (i < argc) + second_level = argv[i]; + else + { + fprintf(stderr, "Missing argument for -s\n"); + return 1; + } + } + else if (strcmp("-i", argv[i]) == 0) + { + if (kernel_image != NULL) + { + fprintf(stderr, "Duplicate definition of -i\n"); + return 1; + } + i++; + if (i < argc) + kernel_image = argv[i]; + else + { + fprintf(stderr, "Missing argument for -i\n"); + return 1; + } + } + else if (strcmp("-b", argv[i]) == 0) + { + if (buffer_size != 0) + { + fprintf(stderr, "Duplicate definition of -b\n"); + return 1; + } + i++; + if (i < argc) + buffer_size = atol(argv[i]); + else + { + fprintf(stderr, "Missing argument for -b\n"); + return 1; + } + } + else if (strcmp("-r", argv[i]) == 0) + { + if (ramdisk != 0) + { + fprintf(stderr, "Duplicate definition of -r\n"); + return 1; + } + i++; + if (i < argc) + ramdisk = argv[i]; + else + { + fprintf(stderr, "Missing argument for -r\n"); + return 1; + } + } + else + { + if (image != NULL) + { + fprintf(stderr, "Unknown parameter %s\n", + argv[i]); + usage(argc, argv); + return 1; + } + image = argv[i]; + } + } + + ret = create_image(first_level, second_level, kernel_image, ramdisk, + buffer_size, image); + return ret; +}