1/** 2 * \file 3 */ 4 5/* 6 * Copyright (c) 2009, ETH Zurich. 7 * All rights reserved. 8 * 9 * This file is distributed under the terms in the attached LICENSE file. 10 * If you do not find this file, copies can be found by writing to: 11 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 12 */ 13 14#include "vmkitmon.h" 15#include "hdd.h" 16#include <stdlib.h> 17#include <string.h> 18 19#define BLOCK_SIZE 512 20 21static void 22calc_chs (struct hdd *hdd) 23{ 24 // assure there is disk with at least 516096 bytes space (16H, 63S, 1C) 25 assert(hdd->disk_image != NULL && hdd->disk_image_size >= 516096); 26 27 /* Here we use a predefined sceme to calculate the CHS of the disk. If the 28 * disk is bigger then 8MiB we use 255 heads, if it is smaller we use 16 29 * heads. This conforms (at least for 8MiB and bigger disks) with the Linux 30 * fdisk tools and their undestanding of the geometry of non physical disks. 31 * Secotors are always 63 per track wich leaves the cylinder value to be the 32 * only one which really needs to be calculated. 33 * Personally I have no idea how wide spread this understanding is!. */ 34 35 // set the heads 36 if (hdd->disk_image_size >= 0x800000) { 37 hdd->heads = 255; 38 } else { 39 hdd->heads = 16; 40 } 41 42 // set the sectors per track 43 hdd->sectors = 63; 44 45 // calculate the size 46 hdd->track_size = hdd->sectors * BLOCK_SIZE; 47 hdd->cylinder_size = hdd->heads * hdd->track_size; 48 // the disk has to be a multiple of the cylinder size, so we round the real 49 // disk size down the nearest multiple of cylinder size 50 size_t real_disk_size = hdd->disk_image_size - 51 (hdd->disk_image_size % hdd->cylinder_size); 52 assert(real_disk_size >= 516096); 53 // now we may safely calculate the cylinders count 54 hdd->cylinders = real_disk_size / hdd->cylinder_size; 55} 56 57struct hdd * 58hdd_new_from_memory (void *disk_image, size_t disk_image_size) 59{ 60 struct hdd *ret = calloc(1, sizeof(struct hdd)); 61 62 ret->disk_image = disk_image; 63 ret->disk_image_size = disk_image_size; 64 65 calc_chs(ret); 66 67 return ret; 68} 69 70void 71hdd_reset (struct hdd *hdd) 72{ 73} 74 75int 76hdd_get_geometry_chs (struct hdd *hdd, uint16_t *cylinders, uint8_t *heads, 77 uint8_t *sectors) 78{ 79 *cylinders = hdd->cylinders; 80 *heads = hdd->heads; 81 *sectors = hdd->sectors; 82 83 return 0; 84} 85 86size_t 87hdd_get_blocks_count (struct hdd *hdd) 88{ 89 return hdd->disk_image_size / BLOCK_SIZE; 90} 91 92int 93hdd_read_blocks (struct hdd *hdd, size_t start_block, size_t *count, 94 uintptr_t buffer) 95{ 96 if (((start_block + *count) * BLOCK_SIZE) > hdd->disk_image_size) { 97 *count = hdd->disk_image_size/BLOCK_SIZE - start_block; 98 } 99 100 memcpy((void *)buffer, (void *)(hdd->disk_image + start_block*BLOCK_SIZE), 101 *count * BLOCK_SIZE); 102 103 return HANDLER_ERR_OK; 104} 105