1 /*
2
3 File: bsd.c
4
5 Copyright (C) 1998-2006,2008 Christophe GRENIER <grenier@cgsecurity.org>
6
7 This software is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write the Free Software Foundation, Inc., 51
19 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #ifdef HAVE_STDLIB_H
27 #include <stdlib.h>
28 #endif
29
30 #include <stdio.h>
31 #include "types.h"
32 #include "common.h"
33 #include "bsd.h"
34 #include "intrf.h"
35 #include "log.h"
36 static int test_BSD(disk_t *disk_car, const struct disklabel*bsd_header, const partition_t *partition, const int verbose, const int dump_ind, const unsigned int max_partitions);
37
check_BSD(disk_t * disk_car,partition_t * partition,const int verbose,const unsigned int max_partitions)38 int check_BSD(disk_t *disk_car,partition_t *partition,const int verbose, const unsigned int max_partitions)
39 {
40 unsigned char *buffer;
41 buffer=(unsigned char*)MALLOC(BSD_DISKLABEL_SIZE);
42 if(disk_car->pread(disk_car, buffer, BSD_DISKLABEL_SIZE, partition->part_offset + 0x200) != BSD_DISKLABEL_SIZE)
43 {
44 free(buffer);
45 return 1;
46 }
47 if(test_BSD(disk_car,(const struct disklabel*)buffer,partition,verbose,0,max_partitions))
48 {
49 free(buffer);
50 return 1;
51 }
52 set_part_name(partition,((const struct disklabel*)buffer)->d_packname,16);
53 free(buffer);
54 return 0;
55 }
56
test_BSD(disk_t * disk_car,const struct disklabel * bsd_header,const partition_t * partition,const int verbose,const int dump_ind,const unsigned int max_partitions)57 static int test_BSD(disk_t *disk_car, const struct disklabel*bsd_header, const partition_t *partition,const int verbose, const int dump_ind, const unsigned int max_partitions)
58 {
59 unsigned int i;
60 const uint16_t* cp;
61 uint16_t crc;
62 if(le32(bsd_header->d_magic) != DISKMAGIC || le32(bsd_header->d_magic2)!=DISKMAGIC)
63 return 0;
64 if(verbose)
65 log_info("\nBSD offset %lu, nbr_part %u, CHS=(%u,%u,%u) ",
66 (long unsigned)(partition->part_offset/disk_car->sector_size),
67 (unsigned int)le16(bsd_header->d_npartitions),
68 (unsigned int)le32(bsd_header->d_ncylinders),
69 (unsigned int)le32(bsd_header->d_ntracks),
70 (unsigned int)le32(bsd_header->d_nsectors));
71 if(le16(bsd_header->d_npartitions) > max_partitions)
72 return 1;
73 crc=0;
74 for(cp=(const uint16_t*)bsd_header;
75 cp<(const uint16_t*)&bsd_header->d_partitions[le16(bsd_header->d_npartitions)];cp++)
76 crc^=*cp;
77 if(crc==0)
78 {
79 if(verbose>0)
80 {
81 log_info("CRC Ok\n");
82 }
83 }
84 else
85 log_error("Bad CRC! CRC must be xor'd by %04X\n",crc);
86 for(i=0;i<le16(bsd_header->d_npartitions);i++)
87 {
88 if(bsd_header->d_partitions[i].p_fstype>0)
89 {
90 if(verbose>0)
91 {
92 /* UFS UFS2 SWAP */
93 log_info("BSD %c: ", 'a'+i);
94 switch(bsd_header->d_partitions[i].p_fstype)
95 {
96 case TST_FS_SWAP:
97 log_info("swap");
98 break;
99 case TST_FS_BSDFFS:
100 log_info("4.2BSD fast filesystem");
101 break;
102 case TST_FS_BSDLFS:
103 log_info("4.4BSD log-structured filesystem");
104 break;
105 default:
106 log_info("type %02X", bsd_header->d_partitions[i].p_fstype);
107 break;
108 }
109 log_info(", offset %9u, size %9u ",
110 (unsigned int)le32(bsd_header->d_partitions[i].p_offset),
111 (unsigned int)le32(bsd_header->d_partitions[i].p_size));
112 log_CHS_from_LBA(disk_car,le32(bsd_header->d_partitions[i].p_offset));
113 log_info(" -> ");
114 log_CHS_from_LBA(disk_car,le32(bsd_header->d_partitions[i].p_offset)+le32(bsd_header->d_partitions[i].p_size)-1);
115 log_info("\n");
116 }
117 }
118 }
119 if(crc)
120 return 1;
121 if(dump_ind!=0)
122 {
123 dump_log(bsd_header,DEFAULT_SECTOR_SIZE);
124 }
125 return 0;
126 }
127
recover_BSD(disk_t * disk_car,const struct disklabel * bsd_header,partition_t * partition,const int verbose,const int dump_ind)128 int recover_BSD(disk_t *disk_car, const struct disklabel*bsd_header,partition_t *partition,const int verbose, const int dump_ind)
129 {
130 int i;
131 int i_max_p_offset=-1;
132 if(test_BSD(disk_car,bsd_header,partition,verbose,dump_ind,BSD_MAXPARTITIONS)==0)
133 {
134 partition->upart_type=UP_FREEBSD;
135 for(i=0;i<BSD_MAXPARTITIONS;i++)
136 {
137 if(bsd_header->d_partitions[i].p_fstype>0)
138 {
139 if(i_max_p_offset==-1 || le32(bsd_header->d_partitions[i].p_offset)>le32(bsd_header->d_partitions[i_max_p_offset].p_offset))
140 i_max_p_offset=i;
141 }
142 }
143 if(i_max_p_offset>=0)
144 partition->part_size=(uint64_t)(le32(bsd_header->d_partitions[i_max_p_offset].p_size) +
145 le32(bsd_header->d_partitions[i_max_p_offset].p_offset) - 1) * disk_car->sector_size - partition->part_offset;
146 else
147 partition->part_size=0;
148 partition->part_type_i386=P_FREEBSD;
149 set_part_name(partition,bsd_header->d_packname,16);
150 partition->info[0]='\0';
151 return 0;
152 }
153 if(test_BSD(disk_car,bsd_header,partition,verbose,dump_ind,OPENBSD_MAXPARTITIONS)==0)
154 {
155 partition->upart_type=UP_OPENBSD;
156 for(i=0;i<OPENBSD_MAXPARTITIONS;i++)
157 {
158 if(bsd_header->d_partitions[i].p_fstype>0)
159 {
160 if(i_max_p_offset==-1 || le32(bsd_header->d_partitions[i].p_offset)>le32(bsd_header->d_partitions[i_max_p_offset].p_offset))
161 i_max_p_offset=i;
162 }
163 }
164 if(i_max_p_offset>=0)
165 partition->part_size=(uint64_t)(le32(bsd_header->d_partitions[i_max_p_offset].p_size) +
166 le32(bsd_header->d_partitions[i_max_p_offset].p_offset) - 1) * disk_car->sector_size - partition->part_offset;
167 else
168 partition->part_size=0;
169 partition->part_type_i386=P_OPENBSD;
170 set_part_name(partition,bsd_header->d_packname,16);
171 partition->info[0]='\0';
172 return 0;
173 }
174 return 1;
175 }
176