0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome/*
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * This file and its contents are supplied under the terms of the
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * Common Development and Distribution License ("CDDL"), version 1.0.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * You may only use this file in accordance with the terms of version
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * 1.0 of the CDDL.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome *
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * A full copy of the text of the CDDL should have accompanied this
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * source. A copy of the CDDL is also available via the Internet at
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * http://www.illumos.org/license/CDDL.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome */
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome/*
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * Copyright 2016 Toomas Soome <tsoome@me.com>
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome */
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome#include <stdio.h>
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome#include <sys/types.h>
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome#include <sys/stat.h>
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome#include <fcntl.h>
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome#include <unistd.h>
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome#include <sys/sysmacros.h>
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome#include <sys/multiboot.h>
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome#include "bblk_einfo.h"
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome#include "boot_utils.h"
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome#include "mboot_extra.h"
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome/*
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * Add version to loader bootblock file. The file should have fake
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * multiboot header and version data will be added at the end of the file.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * MB header is fake in sense that this bootblock is *not* MB compatible,
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * and MB header will only include load_addr and load_end_addr components.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * load_addr will be set to value 0 to indicate the beginning of the file
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * and load_end_addr will be set to the size of the original file.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * The flags value in header must be exactly AOUT kludge.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome *
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * version data is aligned by 8 bytes and whole blootblock will be padded to
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * 512B sector size.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome *
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * To use and verify version data, first find MB header, then load_end_addr
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * will point to the end of the original file, aligned up by 8, is version
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * data implemented as bblk einfo.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome */
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soomevoid
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soomeadd_version(char *file, char *version)
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome{
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome int fd;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome int ret;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome uint32_t buf_size;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome uint32_t mboot_off;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome uint32_t extra;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome uint32_t avail_space;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome multiboot_header_t *mboot;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome struct stat sb;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome char *buf;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome bblk_hs_t hs;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome fd = open(file, O_RDONLY);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome if (fd == -1) {
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome perror("open");
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome return;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome }
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome if (fstat(fd, &sb) == -1) {
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome perror("fstat");
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome close(fd);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome return;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome }
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome /*
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * make sure we have enough space to append EINFO.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome */
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome buf_size = P2ROUNDUP(sb.st_size + SECTOR_SIZE, SECTOR_SIZE);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome buf = malloc(buf_size);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome if (buf == NULL) {
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome perror("malloc");
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome close(fd);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome return;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome }
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome /*
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * read in whole file. we need to access MB header and einfo
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * will create MD5 hash.
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome */
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome ret = read(fd, buf, sb.st_size);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome if (ret != sb.st_size) {
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome perror("read");
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome free(buf);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome close(fd);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome return;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome }
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome close(fd);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome if (find_multiboot(buf, MBOOT_SCAN_SIZE, &mboot_off)
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome != BC_SUCCESS) {
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome printf("Unable to find multiboot header\n");
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome free(buf);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome return;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome }
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome mboot = (multiboot_header_t *)(buf + mboot_off);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome mboot->load_addr = 0;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome mboot->load_end_addr = sb.st_size;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome hs.src_buf = (unsigned char *)buf;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome hs.src_size = sb.st_size;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome /*
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome * this is location for EINFO data
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome */
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome extra = P2ROUNDUP(sb.st_size, 8);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome avail_space = buf_size - extra;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome memset(buf+sb.st_size, 0, buf_size - sb.st_size);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome add_einfo(buf + extra, version, &hs, avail_space);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome fd = open(file, O_WRONLY | O_TRUNC);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome if (fd == -1) {
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome perror("open");
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome free(buf);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome return;
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome }
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome ret = write(fd, buf, buf_size);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome close(fd);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome free(buf);
0cc5983c8a077e6396dc7c492ee928b40bf0fed1Toomas Soome}