1/*	$OpenBSD: file_media.c,v 1.48 2016/01/30 17:21:10 krw Exp $	*/
2
3/*
4 * file_media.c -
5 *
6 * Written by Eryk Vershen
7 */
8
9/*
10 * Copyright 1997,1998 by Apple Computer, Inc.
11 *              All Rights Reserved
12 *
13 * Permission to use, copy, modify, and distribute this software and
14 * its documentation for any purpose and without fee is hereby granted,
15 * provided that the above copyright notice appears in all copies and
16 * that both the copyright notice and this permission notice appear in
17 * supporting documentation.
18 *
19 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE.
22 *
23 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
25 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
26 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
27 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 */
29
30#include <sys/param.h>		/* DEV_BSIZE */
31#include <sys/queue.h>
32
33#include <err.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <unistd.h>
38
39#include "partition_map.h"
40#include "file_media.h"
41
42struct ddmap_ondisk {
43    uint8_t	ddBlock[4];
44    uint8_t	ddSize[2];
45    uint8_t	ddType[2];
46};
47
48struct block0_ondisk {
49    uint8_t	sbSig[2];
50    uint8_t	sbBlkSize[2];
51    uint8_t	sbBlkCount[4];
52    uint8_t	sbDevType[2];
53    uint8_t	sbDevId[2];
54    uint8_t	sbData[4];
55    uint8_t	sbDrvrCount[2];
56    uint8_t	sbDDMap[64];	/* ddmap_ondisk[8] */
57    uint8_t	reserved[430];
58};
59
60struct dpme_ondisk {
61    uint8_t	dpme_signature[2];
62    uint8_t	dpme_reserved_1[2];
63    uint8_t	dpme_map_entries[4];
64    uint8_t	dpme_pblock_start[4];
65    uint8_t	dpme_pblocks[4];
66    uint8_t	dpme_name[DPISTRLEN];
67    uint8_t	dpme_type[DPISTRLEN];
68    uint8_t	dpme_lblock_start[4];
69    uint8_t	dpme_lblocks[4];
70    uint8_t	dpme_flags[4];
71    uint8_t	dpme_boot_block[4];
72    uint8_t	dpme_boot_bytes[4];
73    uint8_t	dpme_load_addr[4];
74    uint8_t	dpme_reserved_2[4];
75    uint8_t	dpme_goto_addr[4];
76    uint8_t	dpme_reserved_3[4];
77    uint8_t	dpme_checksum[4];
78    uint8_t	dpme_processor_id[16];
79    uint8_t	dpme_reserved_4[376];
80};
81
82static int	read_block(int, uint64_t, void *);
83static int	write_block(int, uint64_t, void *);
84
85static int
86read_block(int fd, uint64_t sector, void *address)
87{
88	ssize_t off;
89
90	off = pread(fd, address, DEV_BSIZE, sector * DEV_BSIZE);
91	if (off == DEV_BSIZE)
92		return 1;
93
94	if (off == 0)
95		fprintf(stderr, "end of file encountered");
96	else if (off == -1)
97		warn("reading file failed");
98	else
99		fprintf(stderr, "short read");
100
101	return 0;
102}
103
104static int
105write_block(int fd, uint64_t sector, void *address)
106{
107	ssize_t off;
108
109	off = pwrite(fd, address, DEV_BSIZE, sector * DEV_BSIZE);
110	if (off == DEV_BSIZE)
111		return 1;
112
113	warn("writing to file failed");
114	return 0;
115}
116
117int
118read_block0(int fd, struct partition_map *map)
119{
120	struct block0_ondisk *block0_ondisk;
121	struct ddmap_ondisk ddmap_ondisk;
122	int i;
123
124	block0_ondisk = malloc(sizeof(struct block0_ondisk));
125	if (block0_ondisk == NULL)
126		errx(1, "No memory to read block0");
127
128	if (read_block(fd, 0, block0_ondisk) == 0)
129		return 0;
130
131	memcpy(&map->sbSig, block0_ondisk->sbSig,
132	    sizeof(map->sbSig));
133	map->sbSig = betoh16(map->sbSig);
134	memcpy(&map->sbBlkSize, block0_ondisk->sbBlkSize,
135	    sizeof(map->sbBlkSize));
136	map->sbBlkSize = betoh16(map->sbBlkSize);
137	memcpy(&map->sbBlkCount, block0_ondisk->sbBlkCount,
138	    sizeof(map->sbBlkCount));
139	map->sbBlkCount = betoh32(map->sbBlkCount);
140	memcpy(&map->sbDevType, block0_ondisk->sbDevType,
141	    sizeof(map->sbDevType));
142	map->sbDevType = betoh16(map->sbDevType);
143	memcpy(&map->sbDevId, block0_ondisk->sbDevId,
144	    sizeof(map->sbDevId));
145	map->sbDevId = betoh16(map->sbDevId);
146	memcpy(&map->sbData, block0_ondisk->sbData,
147	    sizeof(map->sbData));
148	map->sbData = betoh32(map->sbData);
149	memcpy(&map->sbDrvrCount, block0_ondisk->sbDrvrCount,
150	    sizeof(map->sbDrvrCount));
151	map->sbDrvrCount = betoh16(map->sbDrvrCount);
152
153	for (i = 0; i < 8; i++) {
154		memcpy(&ddmap_ondisk,
155		    map->sbDDMap+i*sizeof(struct ddmap_ondisk),
156		    sizeof(ddmap_ondisk));
157		memcpy(&map->sbDDMap[i].ddBlock, &ddmap_ondisk.ddBlock,
158		    sizeof(map->sbDDMap[i].ddBlock));
159		map->sbDDMap[i].ddBlock =
160		    betoh32(map->sbDDMap[i].ddBlock);
161		memcpy(&map->sbDDMap[i].ddSize, &ddmap_ondisk.ddSize,
162		    sizeof(map->sbDDMap[i].ddSize));
163		map->sbDDMap[i].ddSize = betoh16(map->sbDDMap[i].ddSize);
164		memcpy(&map->sbDDMap[i].ddType, &ddmap_ondisk.ddType,
165		    sizeof(map->sbDDMap[i].ddType));
166		map->sbDDMap[i].ddType = betoh32(map->sbDDMap[i].ddType);
167	}
168
169	free(block0_ondisk);
170	return 1;
171}
172
173int
174write_block0(int fd, struct partition_map *map)
175{
176	struct block0_ondisk *block0_ondisk;
177	struct ddmap_ondisk ddmap_ondisk;
178	int i, rslt;
179	uint32_t tmp32;
180	uint16_t tmp16;
181
182	block0_ondisk = malloc(sizeof(struct block0_ondisk));
183	if (block0_ondisk == NULL)
184		errx(1, "No memory to write block 0");
185
186	tmp16 = htobe16(map->sbSig);
187	memcpy(block0_ondisk->sbSig, &tmp16,
188	    sizeof(block0_ondisk->sbSig));
189	tmp16 = htobe16(map->sbBlkSize);
190	memcpy(block0_ondisk->sbBlkSize, &tmp16,
191	    sizeof(block0_ondisk->sbBlkSize));
192	tmp32 = htobe32(map->sbBlkCount);
193	memcpy(block0_ondisk->sbBlkCount, &tmp32,
194	    sizeof(block0_ondisk->sbBlkCount));
195	tmp16 = htobe16(map->sbDevType);
196	memcpy(block0_ondisk->sbDevType, &tmp16,
197	    sizeof(block0_ondisk->sbDevType));
198	tmp16 = htobe16(map->sbDevId);
199	memcpy(block0_ondisk->sbDevId, &tmp16,
200	    sizeof(block0_ondisk->sbDevId));
201	tmp32 = htobe32(map->sbData);
202	memcpy(block0_ondisk->sbData, &tmp32,
203	    sizeof(block0_ondisk->sbData));
204	tmp16 = htobe16(map->sbDrvrCount);
205	memcpy(block0_ondisk->sbDrvrCount, &tmp16,
206	    sizeof(block0_ondisk->sbDrvrCount));
207
208	for (i = 0; i < 8; i++) {
209		tmp32 = htobe32(map->sbDDMap[i].ddBlock);
210		memcpy(ddmap_ondisk.ddBlock, &tmp32,
211		    sizeof(ddmap_ondisk.ddBlock));
212		tmp16 = htobe16(map->sbDDMap[i].ddSize);
213		memcpy(&ddmap_ondisk.ddSize, &tmp16,
214		    sizeof(ddmap_ondisk.ddSize));
215		tmp16 = betoh32(map->sbDDMap[i].ddType);
216		memcpy(&ddmap_ondisk.ddType, &tmp16,
217		    sizeof(ddmap_ondisk.ddType));
218		memcpy(map->sbDDMap+i*sizeof(struct ddmap_ondisk),
219		    &ddmap_ondisk, sizeof(ddmap_ondisk));
220	}
221
222	rslt = write_block(fd, 0, block0_ondisk);
223	free(block0_ondisk);
224	return rslt;
225}
226
227int
228read_dpme(int fd, uint64_t sector, struct entry *entry)
229{
230	struct dpme_ondisk *dpme_ondisk;
231
232	dpme_ondisk = malloc(sizeof(struct dpme_ondisk));
233	if (dpme_ondisk == NULL)
234		errx(1, "No memory to read dpme");
235
236	if (read_block(fd, sector, dpme_ondisk) == 0)
237		return 0;
238
239	memcpy(&entry->dpme_signature, dpme_ondisk->dpme_signature,
240	    sizeof(entry->dpme_signature));
241	memcpy(&entry->dpme_map_entries, dpme_ondisk->dpme_map_entries,
242	    sizeof(entry->dpme_map_entries));
243	memcpy(&entry->dpme_pblock_start, dpme_ondisk->dpme_pblock_start,
244	    sizeof(entry->dpme_pblock_start));
245	memcpy(&entry->dpme_pblocks, dpme_ondisk->dpme_pblocks,
246	    sizeof(entry->dpme_pblocks));
247	memcpy(&entry->dpme_lblock_start, dpme_ondisk->dpme_lblock_start,
248	    sizeof(entry->dpme_lblock_start));
249	memcpy(&entry->dpme_lblocks, dpme_ondisk->dpme_lblocks,
250	    sizeof(entry->dpme_lblocks));
251	memcpy(&entry->dpme_flags, dpme_ondisk->dpme_flags,
252	    sizeof(entry->dpme_flags));
253	memcpy(&entry->dpme_boot_block, dpme_ondisk->dpme_boot_block,
254	    sizeof(entry->dpme_boot_block));
255	memcpy(&entry->dpme_boot_bytes, dpme_ondisk->dpme_boot_bytes,
256	    sizeof(entry->dpme_boot_bytes));
257	memcpy(&entry->dpme_load_addr, dpme_ondisk->dpme_load_addr,
258	    sizeof(entry->dpme_load_addr));
259	memcpy(&entry->dpme_goto_addr, dpme_ondisk->dpme_goto_addr,
260	    sizeof(entry->dpme_goto_addr));
261	memcpy(&entry->dpme_checksum, dpme_ondisk->dpme_checksum,
262	    sizeof(entry->dpme_checksum));
263
264	entry->dpme_signature = betoh16(entry->dpme_signature);
265	entry->dpme_map_entries = betoh32(entry->dpme_map_entries);
266	entry->dpme_pblock_start = betoh32(entry->dpme_pblock_start);
267	entry->dpme_pblocks = betoh32(entry->dpme_pblocks);
268	entry->dpme_lblock_start = betoh32(entry->dpme_lblock_start);
269	entry->dpme_lblocks = betoh32(entry->dpme_lblocks);
270	entry->dpme_flags = betoh32(entry->dpme_flags);
271	entry->dpme_boot_block = betoh32(entry->dpme_boot_block);
272	entry->dpme_boot_bytes = betoh32(entry->dpme_boot_bytes);
273	entry->dpme_load_addr = betoh32(entry->dpme_load_addr);
274	entry->dpme_goto_addr = betoh32(entry->dpme_goto_addr);
275	entry->dpme_checksum = betoh32(entry->dpme_checksum);
276
277	memcpy(entry->dpme_reserved_1, dpme_ondisk->dpme_reserved_1,
278	    sizeof(entry->dpme_reserved_1));
279	memcpy(entry->dpme_reserved_2, dpme_ondisk->dpme_reserved_2,
280	    sizeof(entry->dpme_reserved_2));
281	memcpy(entry->dpme_reserved_3, dpme_ondisk->dpme_reserved_3,
282	    sizeof(entry->dpme_reserved_3));
283	memcpy(entry->dpme_reserved_4, dpme_ondisk->dpme_reserved_4,
284	    sizeof(entry->dpme_reserved_4));
285
286	strlcpy(entry->dpme_name, dpme_ondisk->dpme_name,
287	    sizeof(entry->dpme_name));
288	strlcpy(entry->dpme_type, dpme_ondisk->dpme_type,
289	    sizeof(entry->dpme_type));
290	strlcpy(entry->dpme_processor_id, dpme_ondisk->dpme_processor_id,
291	    sizeof(entry->dpme_processor_id));
292
293	free(dpme_ondisk);
294	return 1;
295}
296
297int
298write_dpme(int fd, uint64_t sector, struct entry *entry)
299{
300	struct dpme_ondisk *dpme_ondisk;
301	int rslt;
302	uint32_t tmp32;
303	uint16_t tmp16;
304
305	dpme_ondisk = malloc(sizeof(struct dpme_ondisk));
306	if (dpme_ondisk == NULL)
307		errx(1, "No memory to write dpme");
308
309	memcpy(dpme_ondisk->dpme_name, entry->dpme_name,
310	    sizeof(dpme_ondisk->dpme_name));
311	memcpy(dpme_ondisk->dpme_type, entry->dpme_type,
312	    sizeof(dpme_ondisk->dpme_type));
313	memcpy(dpme_ondisk->dpme_processor_id, entry->dpme_processor_id,
314	    sizeof(dpme_ondisk->dpme_processor_id));
315
316	memcpy(dpme_ondisk->dpme_reserved_1, entry->dpme_reserved_1,
317	    sizeof(dpme_ondisk->dpme_reserved_1));
318	memcpy(dpme_ondisk->dpme_reserved_2, entry->dpme_reserved_2,
319	    sizeof(dpme_ondisk->dpme_reserved_2));
320	memcpy(dpme_ondisk->dpme_reserved_3, entry->dpme_reserved_3,
321	    sizeof(dpme_ondisk->dpme_reserved_3));
322	memcpy(dpme_ondisk->dpme_reserved_4, entry->dpme_reserved_4,
323	    sizeof(dpme_ondisk->dpme_reserved_4));
324
325	tmp16 = htobe16(entry->dpme_signature);
326	memcpy(dpme_ondisk->dpme_signature, &tmp16,
327	    sizeof(dpme_ondisk->dpme_signature));
328	tmp32 = htobe32(entry->dpme_map_entries);
329	memcpy(dpme_ondisk->dpme_map_entries, &tmp32,
330	    sizeof(dpme_ondisk->dpme_map_entries));
331	tmp32 = htobe32(entry->dpme_pblock_start);
332	memcpy(dpme_ondisk->dpme_pblock_start, &tmp32,
333	    sizeof(dpme_ondisk->dpme_pblock_start));
334	tmp32 = htobe32(entry->dpme_pblocks);
335	memcpy(dpme_ondisk->dpme_pblocks, &tmp32,
336	    sizeof(dpme_ondisk->dpme_pblocks));
337	tmp32 = htobe32(entry->dpme_lblock_start);
338	memcpy(dpme_ondisk->dpme_lblock_start, &tmp32,
339	    sizeof(dpme_ondisk->dpme_lblock_start));
340	tmp32 = betoh32(entry->dpme_lblocks);
341	memcpy(dpme_ondisk->dpme_lblocks, &tmp32,
342	    sizeof(dpme_ondisk->dpme_lblocks));
343	tmp32 = betoh32(entry->dpme_flags);
344	memcpy(dpme_ondisk->dpme_flags, &tmp32,
345	    sizeof(dpme_ondisk->dpme_flags));
346	tmp32 = htobe32(entry->dpme_boot_block);
347	memcpy(dpme_ondisk->dpme_boot_block, &tmp32,
348	    sizeof(dpme_ondisk->dpme_boot_block));
349	tmp32 = htobe32(entry->dpme_boot_bytes);
350	memcpy(dpme_ondisk->dpme_boot_bytes, &tmp32,
351	    sizeof(dpme_ondisk->dpme_boot_bytes));
352	tmp32 = betoh32(entry->dpme_load_addr);
353	memcpy(dpme_ondisk->dpme_load_addr, &tmp32,
354	    sizeof(dpme_ondisk->dpme_load_addr));
355	tmp32 = betoh32(entry->dpme_goto_addr);
356	memcpy(dpme_ondisk->dpme_goto_addr, &tmp32,
357	    sizeof(dpme_ondisk->dpme_goto_addr));
358	tmp32 = betoh32(entry->dpme_checksum);
359	memcpy(dpme_ondisk->dpme_checksum, &tmp32,
360	    sizeof(dpme_ondisk->dpme_checksum));
361
362	rslt = write_block(fd, sector, dpme_ondisk);
363	free(dpme_ondisk);
364	return rslt;
365}
366