1/* 2 * volume_id - reads filesystem label and uuid 3 * 4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> 5 * 6 * Based on information taken from dmraid: 7 * Copyright (C) 2004-2006 Heinz Mauelshagen, Red Hat GmbH 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation version 2 of the License. 12 */ 13 14#ifndef _GNU_SOURCE 15#define _GNU_SOURCE 1 16#endif 17 18#ifdef HAVE_CONFIG_H 19# include <config.h> 20#endif 21 22#include <stdio.h> 23#include <stdlib.h> 24#include <unistd.h> 25#include <string.h> 26#include <errno.h> 27#include <ctype.h> 28 29#include "libvolume_id.h" 30#include "util.h" 31 32struct via_meta { 33 uint16_t signature; 34 uint8_t version_number; 35 struct via_array { 36 uint16_t disk_bit_mask; 37 uint8_t disk_array_ex; 38 uint32_t capacity_low; 39 uint32_t capacity_high; 40 uint32_t serial_checksum; 41 } PACKED array; 42 uint32_t serial_checksum[8]; 43 uint8_t checksum; 44} PACKED; 45 46#define VIA_SIGNATURE 0xAA55 47 48/* 8 bit checksum on first 50 bytes of metadata. */ 49static uint8_t meta_checksum(struct via_meta *via) 50{ 51 uint8_t i = 50, sum = 0; 52 53 while (i--) 54 sum += ((uint8_t*) via)[i]; 55 56 return sum == via->checksum; 57} 58 59 60int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size) 61{ 62 const uint8_t *buf; 63 uint64_t meta_off; 64 struct via_meta *via; 65 66 dbg("probing at offset 0x%llx, size 0x%llx", 67 (unsigned long long) off, (unsigned long long) size); 68 69 if (size < 0x10000) 70 return -1; 71 72 meta_off = ((size / 0x200)-1) * 0x200; 73 74 buf = volume_id_get_buffer(id, off + meta_off, 0x200); 75 if (buf == NULL) 76 return -1; 77 78 via = (struct via_meta *) buf; 79 if (le16_to_cpu(via->signature) != VIA_SIGNATURE) 80 return -1; 81 82 if (via->version_number > 1) 83 return -1; 84 85 if (!meta_checksum(via)) 86 return -1; 87 88 volume_id_set_usage(id, VOLUME_ID_RAID); 89 snprintf(id->type_version, sizeof(id->type_version)-1, "%u", via->version_number); 90 id->type = "via_raid_member"; 91 92 return 0; 93} 94