/* * * (c) 2004 Laurent Vivier * */ #include #include #include #include #include #include #include #include "emile.h" #include "emile-first.h" #include "../second/head.h" static void usage(int argc, char** argv) { fprintf(stderr, "Usage: %s -f -s -i -r -b \n", argv[0]); fprintf(stderr, "\nbuild: \n%s\n", SIGNATURE); } 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; } if (kernel_image != NULL) { 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 %d, kernel size %d, buffer size %d\n", read_long(&header.kernel_image_offset), read_long(&header.kernel_image_size), read_long(&header.kernel_size)); printf("ramdisk offset %d, ramdisk size %d\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 %d, size %d\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)) 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 -1; source = open(file, O_RDONLY); if (source < 0) { close(source); return -1; } 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 -1; } } 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 -1; } break; } } printf("%d bytes\n", total); close(source); return total; } static int pad_image(int fd, int size) { static char buffer[SECTOR_SIZE]; int size_written; int total; if (fd < 0) return -1; if (size % SECTOR_SIZE) { fprintf(stderr, "WARNING: pad size is not a multiple of sector size\n"); } memset(buffer, 0, SECTOR_SIZE); total = 0; while (size > 0) { size_written = write(fd, buffer, SECTOR_SIZE); total += size_written; if (size_written != SECTOR_SIZE) { return total; } size -= size_written; } return total; } static int aggregate(int fd, char* first_level, char* second_level, char* kernel_image, char* ramdisk) { int ret; int total; ret = copy_file(fd, first_level); if (ret < 0) return 6; total = ret; ret = copy_file(fd, second_level); if (ret < 0) return 6; total += ret; if (kernel_image != NULL) { ret = copy_file(fd, kernel_image); if (ret < 0) return 6; total += ret; } if (ramdisk != NULL) { ret = copy_file(fd, ramdisk); if (ret < 0) return 6; total += ret; } ret = pad_image(fd, 1474560 - total); 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, "WARNING: kernel image file not defined\n"); } 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; ASSERT_BBH( {fprintf(stderr,"Internal Error: Bad BootBlkHdr size\n"); exit(1);}); ASSERT_PBR( {fprintf(stderr,"Internal Error: Bad ParamBlockRec size\n"); exit(1);}); ASSERT_BB( {fprintf(stderr,"Internal Error: Bad boot block size\n"); exit(1);}); if ((argc != 12) && (argc != 10) && (argc != 8) ) { 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; }