1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2016 Toomas Soome <tsoome@me.com> 14 */ 15 16 #include <stdio.h> 17 #include <sys/types.h> 18 #include <sys/stat.h> 19 #include <fcntl.h> 20 #include <unistd.h> 21 #include <sys/sysmacros.h> 22 #include <sys/multiboot.h> 23 24 #include "bblk_einfo.h" 25 #include "boot_utils.h" 26 #include "mboot_extra.h" 27 28 /* 29 * Add version to loader bootblock file. The file should have fake 30 * multiboot header and version data will be added at the end of the file. 31 * MB header is fake in sense that this bootblock is *not* MB compatible, 32 * and MB header will only include load_addr and load_end_addr components. 33 * load_addr will be set to value 0 to indicate the beginning of the file 34 * and load_end_addr will be set to the size of the original file. 35 * The flags value in header must be exactly AOUT kludge. 36 * 37 * version data is aligned by 8 bytes and whole blootblock will be padded to 38 * 512B sector size. 39 * 40 * To use and verify version data, first find MB header, then load_end_addr 41 * will point to the end of the original file, aligned up by 8, is version 42 * data implemented as bblk einfo. 43 */ 44 45 void 46 add_version(char *file, char *version) 47 { 48 int fd; 49 int ret; 50 uint32_t buf_size; 51 uint32_t mboot_off; 52 uint32_t extra; 53 uint32_t avail_space; 54 multiboot_header_t *mboot; 55 struct stat sb; 56 char *buf; 57 bblk_hs_t hs; 58 59 fd = open(file, O_RDONLY); 60 if (fd == -1) { 61 perror("open"); 62 return; 63 } 64 if (fstat(fd, &sb) == -1) { 65 perror("fstat"); 66 close(fd); 67 return; 68 } 69 70 /* 71 * make sure we have enough space to append EINFO. 72 */ 73 buf_size = P2ROUNDUP(sb.st_size + SECTOR_SIZE, SECTOR_SIZE); 74 buf = malloc(buf_size); 75 if (buf == NULL) { 76 perror("malloc"); 77 close(fd); 78 return; 79 } 80 81 /* 82 * read in whole file. we need to access MB header and einfo 83 * will create MD5 hash. 84 */ 85 ret = read(fd, buf, sb.st_size); 86 if (ret != sb.st_size) { 87 perror("read"); 88 free(buf); 89 close(fd); 90 return; 91 } 92 close(fd); 93 94 if (find_multiboot(buf, MBOOT_SCAN_SIZE, &mboot_off) 95 != BC_SUCCESS) { 96 printf("Unable to find multiboot header\n"); 97 free(buf); 98 return; 99 } 100 101 mboot = (multiboot_header_t *)(buf + mboot_off); 102 mboot->load_addr = 0; 103 mboot->load_end_addr = sb.st_size; 104 105 106 hs.src_buf = (unsigned char *)buf; 107 hs.src_size = sb.st_size; 108 109 /* 110 * this is location for EINFO data 111 */ 112 extra = P2ROUNDUP(sb.st_size, 8); 113 avail_space = buf_size - extra; 114 memset(buf+sb.st_size, 0, buf_size - sb.st_size); 115 add_einfo(buf + extra, version, &hs, avail_space); 116 117 fd = open(file, O_WRONLY | O_TRUNC); 118 if (fd == -1) { 119 perror("open"); 120 free(buf); 121 return; 122 } 123 ret = write(fd, buf, buf_size); 124 close(fd); 125 free(buf); 126 } 127