]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libdisk/disk.c
This commit was generated by cvs2svn to compensate for changes in r52284,
[FreeBSD/FreeBSD.git] / lib / libdisk / disk.c
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
5  * can do whatever you want with this stuff. If we meet some day, and you think
6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7  * ----------------------------------------------------------------------------
8  *
9  * $FreeBSD$
10  *
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <string.h>
18 #include <err.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/ioctl.h>
22 #include <sys/disklabel.h>
23 #include <sys/diskslice.h>
24 #include "libdisk.h"
25
26 #define DOSPTYP_EXTENDED        5
27 #define DOSPTYP_ONTRACK         84
28
29 const char *chunk_n[] = {
30         "whole",
31         "unknown",
32         "fat",
33         "freebsd",
34         "extended",
35         "part",
36         "unused",
37         NULL
38 };
39
40 struct disk *
41 Open_Disk(const char *name)
42 {
43         return Int_Open_Disk(name,0);
44 }
45
46 static u_int32_t
47 Read_Int32(u_int32_t *p)
48 {
49     u_int8_t *bp = (u_int8_t *)p;
50     return bp[0] | (bp[1] << 8) | (bp[2] << 16) | (bp[3] << 24);
51 }
52
53 struct disk *
54 Int_Open_Disk(const char *name, u_long size)
55 {
56         int i,fd;
57         struct diskslices ds;
58         struct disklabel dl;
59         char device[64];
60         struct disk *d;
61         struct dos_partition *dp;
62         void *p;
63         u_long offset = 0;
64
65         strcpy(device,"/dev/r");
66         strcat(device,name);
67
68         d = (struct disk *)malloc(sizeof *d);
69         if(!d) err(1,"malloc failed");
70         memset(d,0,sizeof *d);
71
72         fd = open(device,O_RDONLY);
73         if (fd < 0) {
74 #ifdef DEBUG
75                 warn("open(%s) failed",device);
76 #endif
77                 return 0;
78         }
79
80         memset(&dl,0,sizeof dl);
81         ioctl(fd,DIOCGDINFO,&dl);
82         i = ioctl(fd,DIOCGSLICEINFO,&ds);
83         if (i < 0) {
84 #ifdef DEBUG
85                 warn("DIOCGSLICEINFO(%s) failed",device);
86 #endif
87                 close(fd);
88                 return 0;
89         }
90
91 #ifdef DEBUG
92         for(i=0;i<ds.dss_nslices;i++)
93                 if(ds.dss_slices[i].ds_openmask)
94                         printf("  open(%d)=0x%2x",
95                                 i,ds.dss_slices[i].ds_openmask);
96         printf("\n");
97 #endif
98
99         if (!size)
100                 size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size;
101
102         p = read_block(fd,0);
103         dp = (struct dos_partition*)(p+DOSPARTOFF);
104         for (i=0; i < NDOSPART; i++) {
105                 if (Read_Int32(&dp->dp_start) >= size)
106                     continue;
107                 if (Read_Int32(&dp->dp_start) + Read_Int32(&dp->dp_size) >= size)
108                     continue;
109                 if (!Read_Int32(&dp->dp_size))
110                     continue;
111
112                 if (dp->dp_typ == DOSPTYP_ONTRACK) {
113                         d->flags |= DISK_ON_TRACK;
114                         offset = 63;
115                 }
116
117         }
118         free(p);
119
120         d->bios_sect = dl.d_nsectors;
121         d->bios_hd = dl.d_ntracks;
122
123         d->name = strdup(name);
124
125
126         if (dl.d_ntracks && dl.d_nsectors)
127                 d->bios_cyl = size/(dl.d_ntracks*dl.d_nsectors);
128
129         if (Add_Chunk(d, -offset, size, name, whole, 0, 0))
130 #ifdef DEBUG
131                 warn("Failed to add 'whole' chunk");
132 #else
133                 {}
134 #endif
135
136 #ifdef __i386__
137         for(i=BASE_SLICE;i<ds.dss_nslices;i++) {
138                 char sname[20];
139                 chunk_e ce;
140                 u_long flags=0;
141                 int subtype=0;
142                 if (! ds.dss_slices[i].ds_size)
143                         continue;
144                 ds.dss_slices[i].ds_offset -= offset;
145                 sprintf(sname,"%ss%d",name,i-1);
146                 subtype = ds.dss_slices[i].ds_type;
147                 switch (ds.dss_slices[i].ds_type) {
148                         case 0xa5:
149                                 ce = freebsd;
150                                 break;
151                         case 0x1:
152                         case 0x6:
153                         case 0x4:
154                         case 0xb:
155                         case 0xc:
156                         case 0xe:
157                                 ce = fat;
158                                 break;
159                         case DOSPTYP_EXTENDED:
160                         case 0xf:
161                                 ce = extended;
162                                 break;
163                         default:
164                                 ce = unknown;
165                                 break;
166                 }
167                 if (Add_Chunk(d, ds.dss_slices[i].ds_offset,
168                         ds.dss_slices[i].ds_size, sname, ce, subtype, flags))
169 #ifdef DEBUG
170                         warn("failed to add chunk for slice %d", i - 1);
171 #else
172                         {}
173 #endif
174
175                 if (ds.dss_slices[i].ds_type != 0xa5)
176                         continue;
177                 {
178                 struct disklabel dl;
179                 char pname[20];
180                 int j,k;
181
182                 strcpy(pname,"/dev/r");
183                 strcat(pname,sname);
184                 j = open(pname,O_RDONLY);
185                 if (j < 0) {
186 #ifdef DEBUG
187                         warn("open(%s)",pname);
188 #endif
189                         continue;
190                 }
191                 k = ioctl(j,DIOCGDINFO,&dl);
192                 if (k < 0) {
193 #ifdef DEBUG
194                         warn("ioctl(%s,DIOCGDINFO)",pname);
195 #endif
196                         close(j);
197                         continue;
198                 }
199                 close(j);
200
201                 for(j=0; j <= dl.d_npartitions; j++) {
202                         if (j == RAW_PART)
203                                 continue;
204                         if (j == 3)
205                                 continue;
206                         if (j == dl.d_npartitions) {
207                                 j = 3;
208                                 dl.d_npartitions=0;
209                         }
210                         if (!dl.d_partitions[j].p_size)
211                                 continue;
212                         if (dl.d_partitions[j].p_size +
213                             dl.d_partitions[j].p_offset >
214                             ds.dss_slices[i].ds_size)
215                                 continue;
216                         sprintf(pname,"%s%c",sname,j+'a');
217                         if (Add_Chunk(d,
218                                 dl.d_partitions[j].p_offset +
219                                 ds.dss_slices[i].ds_offset,
220                                 dl.d_partitions[j].p_size,
221                                 pname,part,
222                                 dl.d_partitions[j].p_fstype,
223                                 0) && j != 3)
224 #ifdef DEBUG
225                                 warn(
226                         "Failed to add chunk for partition %c [%lu,%lu]",
227                         j + 'a',dl.d_partitions[j].p_offset,
228                         dl.d_partitions[j].p_size);
229 #else
230                                 {}
231 #endif
232                 }
233                 }
234         }
235 #endif /* __i386__ */
236 #ifdef __alpha__
237         {
238                 struct disklabel dl;
239                 char pname[20];
240                 int j,k;
241
242                 strcpy(pname,"/dev/r");
243                 strcat(pname,name);
244                 j = open(pname,O_RDONLY);
245                 if (j < 0) {
246 #ifdef DEBUG
247                         warn("open(%s)",pname);
248 #endif
249                         goto nolabel;
250                 }
251                 k = ioctl(j,DIOCGDINFO,&dl);
252                 if (k < 0) {
253 #ifdef DEBUG
254                         warn("ioctl(%s,DIOCGDINFO)",pname);
255 #endif
256                         close(j);
257                         goto nolabel;
258                 }
259                 close(j);
260                 All_FreeBSD(d, 1);
261
262                 for(j=0; j <= dl.d_npartitions; j++) {
263                         if (j == RAW_PART)
264                                 continue;
265                         if (j == 3)
266                                 continue;
267                         if (j == dl.d_npartitions) {
268                                 j = 3;
269                                 dl.d_npartitions=0;
270                         }
271                         if (!dl.d_partitions[j].p_size)
272                                 continue;
273                         if (dl.d_partitions[j].p_size +
274                             dl.d_partitions[j].p_offset >
275                             ds.dss_slices[WHOLE_DISK_SLICE].ds_size)
276                                 continue;
277                         sprintf(pname,"%s%c",name,j+'a');
278                         if (Add_Chunk(d,
279                                       dl.d_partitions[j].p_offset,
280                                       dl.d_partitions[j].p_size,
281                                       pname,part,
282                                       dl.d_partitions[j].p_fstype,
283                                       0) && j != 3)
284 #ifdef DEBUG
285                                 warn(
286                                         "Failed to add chunk for partition %c [%lu,%lu]",
287                                         j + 'a',dl.d_partitions[j].p_offset,
288                                         dl.d_partitions[j].p_size);
289 #else
290                         {}
291 #endif
292                 }
293         nolabel:;
294         }
295 #endif /* __alpha__ */
296         close(fd);
297         Fixup_Names(d);
298         Bios_Limit_Chunk(d->chunks,1024*d->bios_hd*d->bios_sect);
299         return d;
300 }
301
302 void
303 Debug_Disk(struct disk *d)
304 {
305         printf("Debug_Disk(%s)",d->name);
306         printf("  flags=%lx",d->flags);
307 #if 0
308         printf("  real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect);
309 #endif
310         printf("  bios_geom=%lu/%lu/%lu = %lu\n",
311                 d->bios_cyl,d->bios_hd,d->bios_sect,
312                 d->bios_cyl*d->bios_hd*d->bios_sect);
313 #if defined(__i386__)
314         printf("  boot1=%p, boot2=%p, bootmgr=%p\n",
315                 d->boot1,d->boot2,d->bootmgr);
316 #elif defined(__alpha__)
317         printf("  boot1=%p, bootmgr=%p\n",
318                 d->boot1,d->bootmgr);
319 #endif
320         Debug_Chunk(d->chunks);
321 }
322
323 void
324 Free_Disk(struct disk *d)
325 {
326         if(d->chunks) Free_Chunk(d->chunks);
327         if(d->name) free(d->name);
328         if(d->bootmgr) free(d->bootmgr);
329         if(d->boot1) free(d->boot1);
330 #if defined(__i386__)
331         if(d->boot2) free(d->boot2);
332 #endif
333         free(d);
334 }
335
336 struct disk *
337 Clone_Disk(struct disk *d)
338 {
339         struct disk *d2;
340
341         d2 = (struct disk*) malloc(sizeof *d2);
342         if(!d2) err(1,"malloc failed");
343         *d2 = *d;
344         d2->name = strdup(d2->name);
345         d2->chunks = Clone_Chunk(d2->chunks);
346         if(d2->bootmgr) {
347                 d2->bootmgr = malloc(DOSPARTOFF);
348                 memcpy(d2->bootmgr,d->bootmgr,DOSPARTOFF);
349         }
350 #if defined(__i386__)
351         if(d2->boot1) {
352                 d2->boot1 = malloc(512);
353                 memcpy(d2->boot1,d->boot1,512);
354         }
355         if(d2->boot2) {
356                 d2->boot2 = malloc(512*15);
357                 memcpy(d2->boot2,d->boot2,512*15);
358         }
359 #elif defined(__alpha__)
360         if(d2->boot1) {
361                 d2->boot1 = malloc(512*15);
362                 memcpy(d2->boot1,d->boot1,512*15);
363         }
364 #endif
365         return d2;
366 }
367
368 #if 0
369 void
370 Collapse_Disk(struct disk *d)
371 {
372
373         while(Collapse_Chunk(d,d->chunks))
374                 ;
375 }
376 #endif
377
378 static char * device_list[] = {"wd", "ad", "sd", "da", "wfd", "fla", "ida", 0};
379
380 char **
381 Disk_Names()
382 {
383     int i,j,k;
384     char disk[25];
385     char diskname[25];
386     struct stat st;
387     struct diskslices ds;
388     int fd;
389     static char **disks;
390
391     disks = malloc(sizeof *disks * (1 + MAX_NO_DISKS));
392     memset(disks,0,sizeof *disks * (1 + MAX_NO_DISKS));
393     k = 0;
394         for (j = 0; device_list[j]; j++) {
395                 for (i = 0; i < MAX_NO_DISKS; i++) {
396                         sprintf(diskname, "%s%d", device_list[j], i);
397                         sprintf(disk, "/dev/r%s", diskname);
398                         if (stat(disk, &st) || !(st.st_mode & S_IFCHR))
399                                 continue;
400                         if ((fd = open(disk, O_RDWR)) == -1)
401                                 continue;
402                         if (ioctl(fd, DIOCGSLICEINFO, &ds) == -1) {
403                                 close(fd);
404                                 continue;
405                         }
406                         disks[k++] = strdup(diskname);
407                         if(k == MAX_NO_DISKS)
408                                 return disks;
409                 }
410         }
411         return disks;
412 }
413
414 void
415 Set_Boot_Mgr(struct disk *d, const u_char *b)
416 {
417         if (d->bootmgr)
418                 free(d->bootmgr);
419         if (!b) {
420                 d->bootmgr = 0;
421         } else {
422                 d->bootmgr = malloc(DOSPARTOFF);
423                 if(!d->bootmgr) err(1,"malloc failed");
424                 memcpy(d->bootmgr,b,DOSPARTOFF);
425         }
426 }
427
428 void
429 Set_Boot_Blocks(struct disk *d, const u_char *b1, const u_char *b2)
430 {
431 #if defined(__i386__)
432         if (d->boot1) free(d->boot1);
433         d->boot1 = malloc(512);
434         if(!d->boot1) err(1,"malloc failed");
435         memcpy(d->boot1,b1,512);
436         if (d->boot2) free(d->boot2);
437         d->boot2 = malloc(15*512);
438         if(!d->boot2) err(1,"malloc failed");
439         memcpy(d->boot2,b2,15*512);
440 #elif defined(__alpha__)
441         if (d->boot1) free(d->boot1);
442         d->boot1 = malloc(15*512);
443         if(!d->boot1) err(1,"malloc failed");
444         memcpy(d->boot1,b1,15*512);
445 #endif
446 }
447
448 const char *
449 slice_type_name( int type, int subtype )
450 {
451         switch (type) {
452                 case 0:         return "whole";
453                 case 1:         switch (subtype) {
454                                         case 1:         return "fat (12-bit)";
455                                         case 2:         return "XENIX /";
456                                         case 3:         return "XENIX /usr";
457                                         case 4:         return "fat (16-bit,<=32Mb)";
458                                         case 5:         return "extended DOS";
459                                         case 6:         return "fat (16-bit,>32Mb)";
460                                         case 7:         return "NTFS/HPFS/QNX";
461                                         case 8:         return "AIX bootable";
462                                         case 9:         return "AIX data";
463                                         case 10:        return "OS/2 bootmgr";
464                                         case 11:        return "fat (32-bit)";
465                                         case 12:        return "fat (32-bit,LBA)";
466                                         case 14:        return "fat (16-bit,>32Mb,LBA)";
467                                         case 15:        return "extended DOS, LBA";
468                                         case 18:        return "Compaq Diagnostic";
469                                         case 84:        return "OnTrack diskmgr";
470                                         case 100:       return "Netware 2.x";
471                                         case 101:       return "Netware 3.x";
472                                         case 115:       return "SCO UnixWare";
473                                         case 128:       return "Minix 1.1";
474                                         case 129:       return "Minix 1.5";
475                                         case 130:       return "linux_swap";
476                                         case 131:       return "ext2fs";
477                                         case 166:       return "OpenBSD FFS";   /* 0xA6 */
478                                         case 169:       return "NetBSD FFS";    /* 0xA9 */
479                                         case 182:       return "OpenBSD";               /* dedicated */
480                                         case 183:       return "bsd/os";
481                                         case 184:       return "bsd/os swap";
482                                         default:        return "unknown";
483                                 }
484                 case 2:         return "fat";
485                 case 3:         switch (subtype) {
486                                         case 165:       return "freebsd";
487                                         default:        return "unknown";
488                                 }
489                 case 4:         return "extended";
490                 case 5:         return "part";
491                 case 6:         return "unused";
492                 default:        return "unknown";
493         }
494 }