cast device_write_sector() to stream_write_sector_t
[emile:mainline.git] / tools / emile_scanbus.c
1 /*
2  *
3  * (c) 2004 Laurent Vivier <Laurent@Vivier.EU>
4  *
5  */
6
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <errno.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <getopt.h>
16
17 #include "libmap.h"
18 #include "libemile.h"
19 #include "device.h"
20
21 #define EMILE_MAX_DISK          16
22 #define EMILE_MAX_DEVNAME       16
23
24 typedef char device_name_t[EMILE_MAX_DEVNAME];
25
26 extern int verbose;
27
28 static void print_size(int nb_blocks, int block_size)
29 {
30         int B, GB, MB, kB;
31
32         B = (nb_blocks * block_size) % 1024;
33
34         if (block_size > 1024)
35                 kB = nb_blocks * (block_size / 1024);
36         else
37                 kB = nb_blocks / (1024 / block_size);
38         
39         MB = kB / 1024;
40         kB = kB % 1024;
41
42         GB = MB / 1024;
43         MB = MB % 1024;
44
45         if (GB)
46                 printf("%d.%03d GB", GB, MB * 1000 / 1024);
47         else if (MB)
48                 printf("%d.%03d MB", MB, kB * 1000 / 1024);
49         else
50                 printf("%d.%03d kB", kB, B * 1000 / 1024);
51 }
52
53 static int emile_scanbus(device_name_t devices[EMILE_MAX_DISK])
54 {
55         int i,j;
56         int fd;
57         device_name_t   dev;
58
59         j = 0;
60
61         /* scan SCSI disks */
62
63         for(i = 0; (i < EMILE_MAX_DISK) && (j < EMILE_MAX_DISK); i++)
64         {
65                 sprintf(dev, "/dev/sd%c", 'a' + i);
66                 fd = open(dev, O_RDONLY);
67                 if (fd == -1)
68                         break;
69                 close(fd);
70                 strncpy(devices[j++], dev, EMILE_MAX_DEVNAME);
71         }
72
73         /* scan ATA disks: EMILE doesn't manage them, but this
74          * allows to have all information on all disks
75          */
76
77         for(i = 0; (i < EMILE_MAX_DISK) && (j < EMILE_MAX_DISK); i++)
78         {
79                 sprintf(dev, "/dev/hd%c", 'a' + i);
80                 fd = open(dev, O_RDONLY);
81                 if (fd == -1)
82                         continue;
83                 close(fd);
84                 strncpy(devices[j++], dev, EMILE_MAX_DEVNAME);
85         }
86
87         return j;
88 }
89
90 void diskinfo(char* devname)
91 {
92         map_t* map;
93         int j;
94         int boottype;
95         char bootblock[BOOTBLOCK_SIZE];
96         int block_size, block_count;
97         int ret;
98         device_io_t device;
99
100         printf("%s:", devname);
101
102         device_sector_size = 512;
103         device.data = (void*)device_open(devname, O_RDONLY);
104         device.write_sector = (stream_write_sector_t)device_write_sector;
105         device.read_sector = (stream_read_sector_t)device_read_sector;
106         device.close = (stream_close_t)device_close;
107         device.get_blocksize = (stream_get_blocksize_t)device_get_blocksize;
108
109         map = map_open(&device);
110         if (map == NULL)
111         {
112                 fprintf(stderr, "Cannot read map of %s\n", devname);
113                 return;
114         }
115
116         ret = map_geometry(map, &block_size, &block_count);
117         if ((ret != -1) && verbose)
118         {
119                 printf(" block size: %d, blocks number: %d (", 
120                         block_size, block_count);
121                 print_size(block_count, block_size);
122                 printf(")\n");
123         }
124         else putchar('\n');
125
126         if (map == NULL)
127         {
128                 printf("\t<No information available>\n");
129                 return;
130         }
131         if (!map_is_valid(map))
132         {
133                 printf("\t<No valid partition map found>\n");
134                 return;
135         }
136         if (map_get_driver_number(map) > 0)
137                 printf("  Drivers\n");
138         for (j = 0; j < map_get_driver_number(map); j++)
139         {
140                 int block, size, type, part;
141                 map_get_driver_info(map, j, 
142                                           &block, &size, &type);
143                 printf("     %d: base: %d size: %d ",
144                        j, block * block_size / 512, 
145                        size * block_size / 512);
146                 printf("type: ");
147                 switch(type)
148                 {
149                         case kDriverTypeMacSCSI:
150                                 printf("SCSI");
151                                 break;
152                         case kDriverTypeMacATA:
153                                 printf("ATA");
154                                 break;
155                         case kDriverTypeMacSCSIChained:
156                                 printf("SCSI chained");
157                                 break;
158                         case kDriverTypeMacATAChained:
159                                 printf("ATA chained");
160                                 break;
161                         default:
162                                 printf("unknown (%04x)\n", type);
163                                 break;
164                 }
165                 part = map_seek_driver_partition(map, 
166                                         block * block_size / 512);
167                 if (part == -1)
168                 {
169                         part = map_seek_driver_partition(map, 
170                                                                block);
171                         if (part == -1)
172                                 printf(" <invalid>\n");
173                         map_read(map, part);
174                 }
175                 else
176                 {
177                         map_read(map, part);
178                         if (!emile_is_apple_driver(map))
179                         {
180                                 part = map_seek_driver_partition(map, 
181                                                                        block);
182                                 if (part == -1)
183                                         printf(" <invalid>\n");
184                                 map_read(map, part);
185                         }
186                 }
187                 printf(" <%d: %s [%s], ", part + 1,
188                         map_get_partition_name(map),
189                         map_get_partition_type(map));
190                 switch(map_get_driver_signature(map))
191                 {
192                         case kPatchDriverSignature:
193                                 printf("patch driver");
194                                 break;
195                         case kSCSIDriverSignature:
196                                 printf("SCSI HD driver");
197                                 break;
198                         case kATADriverSignature:
199                                 printf("ATAPI HD driver");
200                                 break;
201                         case kSCSICDDriverSignature:
202                                 printf("SCSI CDROM driver");
203                                 break;
204                         case kATAPIDriverSignature:
205                                 printf("ATAPI CDROM driver");
206                                 break;
207                         case kDriveSetupHFSSignature:
208                                 printf("Drive Setup HFS partition");
209                                 break;
210                         default:
211                                 printf("Unknown (0x%08lx)", map_get_driver_signature(map));
212                                 break;
213                 }
214                 printf(">\n");
215         }
216         printf("  Partitions\n");
217         for (j = 0; j < map_get_number(map); j++)
218         {
219                 map_read(map, j);
220
221                 if (map_partition_is_startup(map))
222                         printf(" --> ");
223                 else
224                         printf("     ");
225                 printf("%d: ", j + 1);
226                 printf("%16s [%-16s] ", 
227                         map_get_partition_name(map),
228                         map_get_partition_type(map));
229                 map_bootblock_read(map, bootblock);
230                 boottype = map_bootblock_get_type(bootblock);
231                 switch(boottype)
232                 {
233                 case INVALID_BOOTBLOCK:
234                         break;
235                 case APPLE_BOOTBLOCK:
236                         printf(" <Apple bootblock>");
237                         break;
238                 case EMILE_BOOTBLOCK:
239                         printf(" <EMILE bootblock>");
240                         break;
241                 default:
242                         printf(" <unknown bootblock>");
243                         break;
244                 }
245                 if (map_partition_is_bootable(map))
246                         printf(" *\n");
247                 else
248                         putchar('\n');
249                 if (verbose)
250                 {
251                         int start, count;
252                         int bootstart, bootsize, bootaddr, bootentry;
253                         int checksum;
254                         char processor[16];
255                         if (*(unsigned long*)
256                                 (map_get_partition_type(map) + 28))
257                                 printf("                 patch: %s\n", 
258                                         map_get_partition_type(map) + 28);
259
260                         ret = map_get_partition_geometry(map,
261                                                                &start,
262                                                                &count);
263                         if( ret != -1)
264                         {
265                                 printf("                 base:"
266                                        " %d, count: %d (", 
267                                         start, count);
268                                 print_size(count, 512);
269                                 printf(")\n");
270                                 printf("                 flags: 0x%08x\n", 
271                                         map_partition_get_flags(map));
272                                         map_get_bootinfo(map, &bootstart, 
273                                         &bootsize, &bootaddr, 
274                                         &bootentry, &checksum, 
275                                         processor);
276                                 printf("                 "
277                                         "Bootstart: %d, Bootsize: %d\n",
278                                         bootstart, bootsize);
279                                 printf("                 "
280                                         "Bootaddr: %d, Bootentry: %d\n", 
281                                         bootaddr, bootentry);
282                                 printf("                 "
283                                         "Checksum: 0x%04x, Processor: %s\n", 
284                                         checksum, processor);
285                         }
286                 }
287         }
288         map_close(map);
289 }
290
291 void scanbus(void)
292 {
293         device_name_t devname[EMILE_MAX_DISK];
294         int count;
295         int i;
296
297         count = emile_scanbus(devname);
298         if (count == 0)
299         {
300                 if (errno == EACCES)
301                 {
302                         fprintf(stderr, 
303         "ERROR: cannot access to devices (you should try as root...)\n");
304                         return;
305                 }
306                 printf("No disk found\n");
307         }
308         for (i = 0; i < count; i++)
309                 diskinfo(devname[i]);
310 }