Contiki-Inga 3.x
mbr.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Institute of Operating Systems and Computer Networks (TU Brunswick).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * Author: Christoph Peltz <peltz@ibr.cs.tu-bs.de>
30  */
31 
32 /**
33  * \addtogroup Drivers
34  * @{
35  *
36  * \addtogroup mbr_driver
37  * @{
38  */
39 
40 /**
41  * \file
42  * MBR Support implementation
43  * \author
44  * Christoph Peltz <peltz@ibr.cs.tu-bs.de>
45  */
46 
47 #include "mbr.h"
48 #include <string.h>
49 #include <stdio.h>
50 void
51 mbr_init(struct mbr *mbr) {
52  int i = 0;
53 
54  for (i = 0; i < 4; ++i) {
55  // Everything else is set to 0
56  memset((&(mbr->partition[i])), 0, 16);
57  mbr->partition[i].status = 0x01;
58  }
59 }
60 /*----------------------------------------------------------------------------*/
61 int
62 mbr_read(struct diskio_device_info *from, struct mbr *to) {
63  uint8_t mbr_buffer[512];
64 
65  int ret = diskio_read_block(from, 0, mbr_buffer);
66  int i = 0;
67 
68  if (ret != 0) {
69  return MBR_ERROR_DISKIO_ERROR;
70  }
71 
72  /*test if 0x55AA is at the end, otherwise it is no MBR*/
73  if (mbr_buffer[510] == 0x55 && mbr_buffer[511] == 0xAA) {
74  for (i = 0; i < 4; ++i) {
75  memcpy(&(to->partition[i]), &(mbr_buffer[446 + 16 * i]), 16);
76  }
77  return MBR_SUCCESS;
78  }
79 
80  return MBR_ERROR_NO_MBR_FOUND;
81 }
82 /*----------------------------------------------------------------------------*/
83 int
84 mbr_write(struct mbr *from, struct diskio_device_info *to) {
85  int i = 0;
86  uint8_t mbr_buffer[512];
87 
88  memset(mbr_buffer, 0, 512);
89 
90  for (i = 0; i < 4; ++i) {
91  memcpy(&(mbr_buffer[446 + 16 * i]), &(from->partition[i]), 16);
92  }
93 
94  mbr_buffer[510] = 0x55;
95  mbr_buffer[511] = 0xAA;
96 
97  return diskio_write_block(to, 0, mbr_buffer);
98 }
99 /*----------------------------------------------------------------------------*/
100 int
101 mbr_addPartition(struct mbr *mbr, uint8_t part_num, uint8_t part_type, uint32_t start, uint32_t len) {
102  int ret = 0;
103  uint8_t sectors_per_track = 63, heads_per_cylinder = 16;
104  uint16_t cylinder = 0;
105 
106  ret = mbr_hasPartition(mbr, part_num);
107  if (ret != 0) {
108  return MBR_ERROR_PARTITION_EXISTS;
109  }
110 
111  mbr->partition[part_num - 1].status = 0x00;
112 
113  cylinder = start / (sectors_per_track * heads_per_cylinder);
114  mbr->partition[part_num - 1].chs_first_sector[0] = (start / sectors_per_track) % heads_per_cylinder;
115  mbr->partition[part_num - 1].chs_first_sector[1] = ((uint8_t) ((cylinder >> 8) << 6)) + ((start % sectors_per_track) + 1);
116  mbr->partition[part_num - 1].chs_first_sector[2] = (uint8_t) cylinder;
117 
118  mbr->partition[part_num - 1].type = part_type;
119 
120  // the end address isn't capable of fitting into a uint32_t
121  // or the end address is further out then chs addressing is capable of
122  // 1023*254*63 is the max value for chs
123  if (start + len <= start || start + len >= ((uint32_t) 1023)*254 * 63) {
124  mbr->partition[part_num - 1].chs_last_sector[0] = 254;
125  mbr->partition[part_num - 1].chs_last_sector[1] = ((uint8_t) ((1023 >> 8) << 6)) + 63;
126  mbr->partition[part_num - 1].chs_last_sector[2] = (uint8_t) 1023;
127  } else {
128  cylinder = (start + len) / (sectors_per_track * heads_per_cylinder);
129  mbr->partition[part_num - 1].chs_last_sector[0] = ((start + len) / sectors_per_track) % heads_per_cylinder;
130  mbr->partition[part_num - 1].chs_last_sector[1] = ((uint8_t) ((cylinder >> 8) << 6)) + (((start + len) % sectors_per_track) + 1);
131  mbr->partition[part_num - 1].chs_last_sector[2] = (uint8_t) cylinder;
132  }
133  mbr->partition[part_num - 1].lba_first_sector = start;
134  mbr->partition[part_num - 1].lba_num_sectors = len;
135 
136  return MBR_SUCCESS;
137 }
138 /*----------------------------------------------------------------------------*/
139 int
140 mbr_delPartition(struct mbr *mbr, uint8_t part_num) {
141  if (part_num > 4 || part_num < 1) {
142  return MBR_ERROR_INVALID_PARTITION;
143  }
144 
145  // Set Status to invalid (everything other than 0x00 and 0x80 is invalid
146  mbr->partition[part_num - 1].status = 0x01;
147  // Everything else is set to 0
148  memset((&(mbr->partition[part_num - 1])) + 1, 0, 15);
149 
150  return MBR_SUCCESS;
151 }
152 /*----------------------------------------------------------------------------*/
153 int
154 mbr_hasPartition(struct mbr *mbr, uint8_t part_num) {
155  if (part_num > 4 || part_num < 1) {
156  return 0;
157  }
158 
159  if (mbr->partition[part_num - 1].status != 0x00 && mbr->partition[part_num - 1].status != 0x80) {
160  return 0;
161  }
162 
163  if (mbr->partition[part_num - 1].type == 0) {
164  return 0;
165  }
166 
167  return 1;
168 }