176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ----------------------------------------------------------------------- * 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2010 Shao Miller 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2010-2012 Michal Soltys 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Permission is hereby granted, free of charge, to any person 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * obtaining a copy of this software and associated documentation 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * files (the "Software"), to deal in the Software without 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * restriction, including without limitation the rights to use, 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * copy, modify, merge, publish, distribute, sublicense, and/or 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * sell copies of the Software, and to permit persons to whom 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the Software is furnished to do so, subject to the following 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * conditions: 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * The above copyright notice and this permission notice shall 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * be included in all copies or substantial portions of the Software. 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * OTHER DEALINGS IN THE SOFTWARE. 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- */ 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <com32.h> 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdlib.h> 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h> 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h> 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdint.h> 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <dprintf.h> 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <syslinux/config.h> 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "chain.h" 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "options.h" 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "utility.h" 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "partiter.h" 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "mangle.h" 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const char cmldr_signature[8] = "cmdcons"; 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Create boot info table: needed when you want to chainload 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * another version of ISOLINUX (or another bootlaoder that needs 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the -boot-info-table switch of mkisofs) 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (will only work when run from ISOLINUX) 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint manglef_isolinux(struct data_area *data) 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const union syslinux_derivative_info *sdi; 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned char *isolinux_bin; 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t *checksum, *chkhead, *chktail; 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t file_lba = 0; 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(opt.file && opt.isolinux)) 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdi = syslinux_derivative_info(); 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdi->c.filesystem != SYSLINUX_FS_ISOLINUX) { 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("The isolinux= option is only valid when run from ISOLINUX."); 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Boot info table info (integers in little endian format) 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Offset Name Size Meaning 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8 bi_pvd 4 bytes LBA of primary volume descriptor 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12 bi_file 4 bytes LBA of boot file 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16 bi_length 4 bytes Boot file length in bytes 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20 bi_csum 4 bytes 32-bit checksum 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24 bi_reserved 40 bytes Reserved 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman The 32-bit checksum is the sum of all the 32-bit words in the 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman boot file starting at byte offset 64. All linear block 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman addresses (LBAs) are given in CD sectors (normally 2048 bytes). 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LBA of primary volume descriptor should already be set to 16. 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman isolinux_bin = (unsigned char *)data->data; 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Get LBA address of bootfile */ 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman file_lba = get_file_lba(opt.file); 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (file_lba == 0) { 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Failed to find LBA offset of the boot file."); 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Set it */ 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *((uint32_t *) & isolinux_bin[12]) = file_lba; 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Set boot file length */ 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *((uint32_t *) & isolinux_bin[16]) = data->size; 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Calculate checksum */ 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman checksum = (uint32_t *) & isolinux_bin[20]; 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman chkhead = (uint32_t *) & isolinux_bin[64]; 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman chktail = (uint32_t *) & isolinux_bin[data->size & ~3u]; 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *checksum = 0; 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (chkhead < chktail) 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *checksum += *chkhead++; 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Deal with possible fractional dword at the end; 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * this *should* never happen... 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (data->size & 3) { 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t xword = 0; 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(&xword, chkhead, data->size & 3); 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *checksum += xword; 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbail: 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Legacy grub's stage2 chainloading 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint manglef_grub(const struct part_iter *iter, struct data_area *data) 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Layout of stage2 file (from byte 0x0 to 0x270) */ 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct grub_stage2_patch_area { 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x0 to 0x205 */ 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char unknown[0x206]; 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x206: compatibility version number major */ 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t compat_version_major; 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x207: compatibility version number minor */ 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t compat_version_minor; 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x208: install_partition variable */ 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct { 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x208: sub-partition in sub-partition part2 */ 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t part3; 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x209: sub-partition in top-level partition */ 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t part2; 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x20a: top-level partiton number */ 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t part1; 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x20b: BIOS drive number (must be 0) */ 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t drive; 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } __attribute__ ((packed)) install_partition; 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x20c: deprecated (historical reason only) */ 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t saved_entryno; 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x210: stage2_ID: will always be STAGE2_ID_STAGE2 = 0 in stage2 */ 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t stage2_id; 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x211: force LBA */ 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t force_lba; 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x212: version string (will probably be 0.97) */ 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char version_string[5]; 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x217: config filename */ 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char config_file[89]; 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 0x270: start of code (after jump from 0x200) */ 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char codestart[1]; 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } __attribute__ ((packed)) *stage2; 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(opt.file && opt.grub)) 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (data->size < sizeof *stage2) { 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("The file specified by grub=<loader> is too small to be stage2 of GRUB Legacy."); 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman stage2 = data->data; 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Check the compatibility version number to see if we loaded a real 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * stage2 file or a stage2 file that we support. 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (stage2->compat_version_major != 3 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman || stage2->compat_version_minor != 2) { 17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("The file specified by grub=<loader> is not a supported stage2 GRUB Legacy binary."); 17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * GRUB Legacy wants the partition number in the install_partition 18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * variable, located at offset 0x208 of stage2. 18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * When GRUB Legacy is loaded, it is located at memory address 0x8208. 18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * It looks very similar to the "boot information format" of the 18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Multiboot specification: 18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * http://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format 18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 0x208 = part3: sub-partition in sub-partition part2 19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 0x209 = part2: sub-partition in top-level partition 19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 0x20a = part1: top-level partition number 19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 0x20b = drive: BIOS drive number (must be 0) 19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * GRUB Legacy doesn't store the BIOS drive number at 0x20b, but at 19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * another location. 19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Partition numbers always start from zero. 19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Unused partition bytes must be set to 0xFF. 19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * We only care about top-level partition, so we only need to change 20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * "part1" to the appropriate value: 20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * -1: whole drive (default) (-1 = 0xFF) 20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 0-3: primary partitions 20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 4-*: logical partitions 20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman stage2->install_partition.part1 = iter->index - 1; 20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Grub Legacy reserves 89 bytes (from 0x8217 to 0x826f) for the 21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * config filename. The filename passed via grubcfg= will overwrite 21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the default config filename "/boot/grub/menu.lst". 21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (opt.grubcfg) { 21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (strlen(opt.grubcfg) >= sizeof stage2->config_file) { 21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("The config filename length can't exceed 88 characters."); 21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman strcpy((char *)stage2->config_file, opt.grubcfg); 22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbail: 22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0 22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Dell's DRMK chainloading. 22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint manglef_drmk(struct data_area *data) 23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * DRMK entry is different than MS-DOS/PC-DOS 23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * A new size, aligned to 16 bytes to ease use of ds:[bp+28]. 23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * We only really need 4 new, usable bytes at the end. 23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(opt.file && opt.drmk)) 23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t tsize = (data->size + 19) & 0xfffffff0; 24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const union syslinux_derivative_info *sdi; 24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint64_t fs_lba; 24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdi = syslinux_derivative_info(); 24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* We should lookup the Syslinux partition offset and use it */ 24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fs_lba = *sdi->disk.partoffset; 24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fs_lba should be verified against the disk as some DRMK 25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * variants will check and fail if it does not match 25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dprintf(" fs_lba offset is %d\n", fs_lba); 25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* DRMK only uses a DWORD */ 25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (fs_lba > 0xffffffff) { 25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("LBA very large; Only using lower 32 bits; DRMK will probably fail."); 25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.ss = opt.regs.fs = opt.regs.gs = 0; /* Used before initialized */ 25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!realloc(data->data, tsize)) { 26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Failed to realloc for DRMK."); 26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman data->size = tsize; 26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* ds:bp is assumed by DRMK to be the boot sector */ 26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* offset 28 is the FAT HiddenSectors value */ 26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.ds = (tsize >> 4) + (opt.fseg - 2); 26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* "Patch" into tail of the new space */ 26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint32_t *)((char*)data->data + tsize - 4) = fs_lba; 26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbail: 27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif 27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Adjust BPB common function */ 27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int mangle_bpb(const struct part_iter *iter, struct data_area *data, const char *tag) 27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int type = bpb_detect(data->data, tag); 27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int off = drvoff_detect(type); 28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* BPB: hidden sectors 64bit - exFAT only for now */ 28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (type == bpbEXF) 28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint64_t *) ((char *)data->data + 0x40) = iter->abs_lba; 28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* BPB: hidden sectors 32bit*/ 28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (bpbV34 <= type && type <= bpbV70) { 28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (iter->abs_lba < ~0u) 28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint32_t *) ((char *)data->data + 0x1c) = iter->abs_lba; 28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* won't really help much, but ... */ 29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint32_t *) ((char *)data->data + 0x1c) = ~0u; 29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* BPB: hidden sectors 16bit*/ 29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (bpbV30 <= type && type <= bpbV32) { 29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (iter->abs_lba < 0xFFFF) 29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint16_t *) ((char *)data->data + 0x1c) = iter->abs_lba; 29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* won't really help much, but ... */ 29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint16_t *) ((char *)data->data + 0x1c) = (uint16_t)~0u; 29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* BPB: legacy geometry */ 30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (bpbV30 <= type && type <= bpbV70) { 30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (iter->di.cbios) 30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint32_t *)((char *)data->data + 0x18) = (iter->di.head << 16) | iter->di.spt; 30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else { 30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (iter->di.disk & 0x80) 30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint32_t *)((char *)data->data + 0x18) = 0x00FF003F; 30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint32_t *)((char *)data->data + 0x18) = 0x00020012; 30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* BPB: drive */ 31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (off >= 0) { 31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint8_t *)((char *)data->data + off) = (opt.swap ? iter->di.disk & 0x80 : iter->di.disk); 31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Adjust BPB of a BPB-compatible file 32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint manglef_bpb(const struct part_iter *iter, struct data_area *data) 32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(opt.file && opt.filebpb)) 32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return mangle_bpb(iter, data, "file"); 32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Adjust BPB of a sector 33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint mangles_bpb(const struct part_iter *iter, struct data_area *data) 33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(opt.sect && opt.setbpb)) 33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return mangle_bpb(iter, data, "sect"); 33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This function performs full BPB patching, analogously to syslinux's 34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * native BSS. 34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint manglesf_bss(struct data_area *sec, struct data_area *fil) 34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int type1, type2; 34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman size_t cnt = 0; 34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(opt.sect && opt.file && opt.bss)) 35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman type1 = bpb_detect(fil->data, "bss/file"); 35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman type2 = bpb_detect(sec->data, "bss/sect"); 35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!type1 || !type2) { 35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Couldn't determine the BPB type for option 'bss'."); 35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (type1 != type2) { 36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Option 'bss' can't be used,\n" 36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "when a sector and a file have incompatible BPBs."); 36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Copy common 2.0 data */ 36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy((char *)fil->data + 0x0B, (char *)sec->data + 0x0B, 0x0D); 36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Copy 3.0+ data */ 37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (type1 <= bpbV30) { 37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cnt = 0x06; 37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (type1 <= bpbV32) { 37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cnt = 0x08; 37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (type1 <= bpbV34) { 37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cnt = 0x0C; 37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (type1 <= bpbV40) { 37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cnt = 0x2E; 37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (type1 <= bpbVNT) { 37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cnt = 0x3C; 38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (type1 <= bpbV70) { 38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cnt = 0x42; 38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (type1 <= bpbEXF) { 38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cnt = 0x60; 38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy((char *)fil->data + 0x18, (char *)sec->data + 0x18, cnt); 38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbail: 38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Save sector. 39476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 39576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint mangles_save(const struct part_iter *iter, const struct data_area *data, void *org) 39676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 39776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(opt.sect && opt.save)) 39876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 39976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 40076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (memcmp(org, data->data, data->size)) { 40176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (disk_write_sectors(&iter->di, iter->abs_lba, data->data, 1)) { 40276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Cannot write the updated sector."); 40376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 40476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 40576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* function can be called again */ 40676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(org, data->data, data->size); 40776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 40876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 40976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 41076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbail: 41176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 41276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 41376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 41476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 41576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * To boot the Recovery Console of Windows NT/2K/XP we need to write 41676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the string "cmdcons\0" to memory location 0000:7C03. 41776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Memory location 0000:7C00 contains the bootsector of the partition. 41876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 41976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint mangles_cmldr(struct data_area *data) 42076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 42176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(opt.sect && opt.cmldr)) 42276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 42376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 42476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy((char *)data->data + 3, cmldr_signature, sizeof cmldr_signature); 42576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 42676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 42776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 42876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Set common registers */ 42976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint mangler_init(const struct part_iter *iter) 43076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 43176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Set initial registry values */ 43276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (opt.file) { 43376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.cs = opt.regs.ds = opt.regs.ss = opt.fseg; 43476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.ip = opt.fip; 43576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 43676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.cs = opt.regs.ds = opt.regs.ss = opt.sseg; 43776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.ip = opt.sip; 43876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 43976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (opt.regs.ip == 0x7C00 && !opt.regs.cs) 44176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.esp.l = 0x7C00; 44276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* DOS kernels want the drive number in BL instead of DL. Indulge them. */ 44476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.ebx.b[0] = opt.regs.edx.b[0] = iter->di.disk; 44576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 44776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 44876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ds:si & ds:bp */ 45076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint mangler_handover(const struct part_iter *iter, const struct data_area *data) 45176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 45276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (opt.file && opt.maps && !opt.hptr) { 45376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.esi.l = opt.regs.ebp.l = opt.soff; 45476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.ds = opt.sseg; 45576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.eax.l = 0; 45676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (opt.hand) { 45776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* base is really 0x7be */ 45876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.esi.l = opt.regs.ebp.l = data->base; 45976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.ds = 0; 46076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (iter->index && iter->type == typegpt) /* must be iterated and GPT */ 46176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.eax.l = 0x54504721; /* '!GPT' */ 46276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 46376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.eax.l = 0; 46476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 46576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 46676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 46776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 46876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 46976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 47076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * GRLDR of GRUB4DOS wants the partition number in DH: 47176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * -1: whole drive (default) 47276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 0-3: primary partitions 47376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 4-*: logical partitions 47476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 47576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint mangler_grldr(const struct part_iter *iter) 47676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 47776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (opt.grldr) 47876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman opt.regs.edx.b[1] = iter->index - 1; 47976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 48076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 48176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 48276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 48376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 48476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * try to copy values from temporary iterator, if positions match 48576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 48676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void mbrcpy(struct part_iter *diter, struct part_iter *siter) 48776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 48876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (diter->dos.cebr_lba == siter->dos.cebr_lba && 48976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman diter->di.disk == siter->di.disk) { 49076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(diter->data, siter->data, sizeof(struct disk_dos_mbr)); 49176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 49276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 49376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 49476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int fliphide(struct part_iter *iter, struct part_iter *miter) 49576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 49676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct disk_dos_part_entry *dp; 49776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static const uint16_t mask = 49876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (1 << 0x01) | (1 << 0x04) | (1 << 0x06) | 49976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (1 << 0x07) | (1 << 0x0b) | (1 << 0x0c) | (1 << 0x0e); 50076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t t; 50176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dp = (struct disk_dos_part_entry *)iter->record; 50376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman t = dp->ostype; 50476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((t <= 0x1f) && ((mask >> (t & ~0x10u)) & 1)) { 50676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* It's a hideable partition type */ 50776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (miter->index == iter->index || opt.hide & HIDE_REV) 50876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman t &= ~0x10u; /* unhide */ 50976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 51076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman t |= 0x10u; /* hide */ 51176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 51276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (dp->ostype != t) { 51376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dp->ostype = t; 51476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 51576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 51676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 51776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 51876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 51976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 52076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * miter - iterator we match against 52176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * hide bits meaning: 52276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ..| - enable (1) / disable (0) 52376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * .|. - all (1) / pri (0) 52476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * |.. - unhide (1) / hide (0) 52576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 52676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint manglepe_hide(struct part_iter *miter) 52776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 52876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int wb = 0, werr = 0; 52976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct part_iter *iter = NULL; 53076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int ridx; 53176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(opt.hide & HIDE_ON)) 53376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 53476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (miter->type != typedos) { 53676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Option '[un]hide[all]' works only for legacy (DOS) partition scheme."); 53776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 53876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 53976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 54076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (miter->index > 4 && !(opt.hide & HIDE_EXT)) 54176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman warn("Specified partition is logical, so it can't be unhidden without 'unhideall'."); 54276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 54376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(iter = pi_begin(&miter->di, PIF_STEPALL | opt.piflags))) 54476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 54576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 54676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (!pi_next(iter) && !werr) { 54776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ridx = iter->index0; 54876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(opt.hide & HIDE_EXT) && ridx > 3) 54976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; /* skip when we're constrained to pri only */ 55076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (iter->index != -1) 55276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman wb |= fliphide(iter, miter); 55376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 55576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * we have to update mbr and each extended partition, but only if 55676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * changes (wb) were detected and there was no prior write error (werr) 55776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 55876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (ridx >= 3 && wb && !werr) { 55976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mbrcpy(miter, iter); 56076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman werr |= disk_write_sectors(&iter->di, iter->dos.cebr_lba, iter->data, 1); 56176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman wb = 0; 56276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 56376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 56476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 56576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (iter->status < 0) 56676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 56776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 56876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* last update */ 56976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (wb && !werr) { 57076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mbrcpy(miter, iter); 57176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman werr |= disk_write_sectors(&iter->di, iter->dos.cebr_lba, iter->data, 1); 57276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 57376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (werr) 57476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman warn("Failed to write E/MBR during '[un]hide[all]'."); 57576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 57676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbail: 57776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pi_del(&iter); 57876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 57976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 58076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 58176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int updchs(struct part_iter *iter, int ext) 58276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 58376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct disk_dos_part_entry *dp; 58476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t ochs1, ochs2, lba; 58576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 58676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dp = (struct disk_dos_part_entry *)iter->record; 58776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!ext) { 58876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* primary or logical */ 58976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman lba = (uint32_t)iter->abs_lba; 59076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 59176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* extended */ 59276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dp += 1; 59376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman lba = iter->dos.nebr_lba; 59476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 59576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ochs1 = *(uint32_t *)dp->start; 59676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ochs2 = *(uint32_t *)dp->end; 59776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 59876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 59976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * We have to be a bit more careful here in case of 0 start and/or length; 60076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * start = 0 would be converted to the beginning of the disk (C/H/S = 60176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 0/0/1) or the [B]EBR, length = 0 would actually set the end CHS to be 60276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * lower than the start CHS. 60376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 60476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Both are harmless in case of a hole (and in non-hole case will make 60576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * partiter complain about corrupt layout if PIF_STRICT is set), but it 60676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * makes everything look silly and not really correct. 60776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 60876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Thus the approach as seen below. 60976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 61076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 61176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (dp->start_lba || iter->index != -1) { 61276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman lba2chs(&dp->start, &iter->di, lba, L2C_CADD); 61376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 61476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&dp->start, 0, sizeof dp->start); 61576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 61676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 61776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((dp->start_lba || iter->index != -1) && dp->length) { 61876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman lba2chs(&dp->end, &iter->di, lba + dp->length - 1, L2C_CADD); 61976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 62076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&dp->end, 0, sizeof dp->end); 62176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 62276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 62376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 62476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint32_t *)dp->start != ochs1 || 62576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *(uint32_t *)dp->end != ochs2; 62676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 62776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 62876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 62976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * miter - iterator we match against 63076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 63176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint manglepe_fixchs(struct part_iter *miter) 63276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 63376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int wb = 0, werr = 0; 63476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct part_iter *iter = NULL; 63576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int ridx; 63676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!opt.fixchs) 63876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 63976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 64076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (miter->type != typedos) { 64176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Option 'fixchs' works only for legacy (DOS) partition scheme."); 64276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 64376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 64476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 64576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(iter = pi_begin(&miter->di, PIF_STEPALL | opt.piflags))) 64676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 64776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 64876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (!pi_next(iter) && !werr) { 64976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ridx = iter->index0; 65076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 65176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman wb |= updchs(iter, 0); 65276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (ridx > 3) 65376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman wb |= updchs(iter, 1); 65476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 65576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 65676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * we have to update mbr and each extended partition, but only if 65776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * changes (wb) were detected and there was no prior write error (werr) 65876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 65976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (ridx >= 3 && wb && !werr) { 66076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mbrcpy(miter, iter); 66176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman werr |= disk_write_sectors(&iter->di, iter->dos.cebr_lba, iter->data, 1); 66276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman wb = 0; 66376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 66476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 66576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 66676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (iter->status < 0) 66776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto bail; 66876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 66976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* last update */ 67076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (wb && !werr) { 67176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mbrcpy(miter, iter); 67276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman werr |= disk_write_sectors(&iter->di, iter->dos.cebr_lba, iter->data, 1); 67376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 67476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (werr) 67576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman warn("Failed to write E/MBR during 'fixchs'."); 67676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 67776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbail: 67876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pi_del(&iter); 67976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 68076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 68176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 68276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* vim: set ts=8 sts=4 sw=4 noet: */ 683