25
25
#include <grub/dl.h>
26
26
#include <grub/types.h>
29
#define GRUB_UFS_MAGIC 0x19540119
31
29
#define GRUB_UFS_MAGIC 0x11954
30
#define GRUB_UFS2_MAGIC 0x19540119
34
31
#define GRUB_UFS_INODE 2
35
32
#define GRUB_UFS_FILETYPE_DIR 4
36
33
#define GRUB_UFS_FILETYPE_LNK 10
47
44
#define GRUB_UFS_VOLNAME_LEN 32
49
46
/* Calculate in which group the inode can be found. */
47
#define inode_group(inode,sblock) ()
50
49
#define UFS_BLKSZ(sblock) (grub_le_to_cpu32 (sblock->bsize))
52
#define INODE(data,field) data->inode. field
54
#define INODE_ENDIAN(data,field,bits1,bits2) grub_le_to_cpu##bits2 (data->inode.field)
56
#define INODE_ENDIAN(data,field,bits1,bits2) grub_le_to_cpu##bits1 (data->inode.field)
51
#define INODE(data,field) (data->ufs_type == UFS1 ? \
52
data->inode. field : data->inode2. field)
53
#define INODE_ENDIAN(data,field,bits1,bits2) (data->ufs_type == UFS1 ? \
54
grub_le_to_cpu##bits1 (data->inode.field) : \
55
grub_le_to_cpu##bits2 (data->inode2.field))
59
56
#define INODE_SIZE(data) INODE_ENDIAN (data,size,32,64)
60
57
#define INODE_NBLOCKS(data) INODE_ENDIAN (data,nblocks,32,64)
62
59
#define INODE_MODE(data) INODE_ENDIAN (data,mode,16,16)
69
#define UFS_INODE_PER_BLOCK 2
71
#define UFS_INODE_PER_BLOCK 4
60
#define INODE_BLKSZ(data) (data->ufs_type == UFS1 ? 4 : 8)
73
61
#define INODE_DIRBLOCKS(data,blk) INODE_ENDIAN \
74
62
(data,blocks.dir_blocks[blk],32,64)
75
63
#define INODE_INDIRBLOCKS(data,blk) INODE_ENDIAN \
160
174
grub_uint8_t unused[24];
161
175
} __attribute__ ((packed));
164
struct grub_ufs_inode
167
grub_uint16_t nlinks;
178
grub_uint32_t dir_blocks[GRUB_UFS_DIRBLKS];
179
grub_uint32_t indir_blocks[GRUB_UFS_INDIRBLKS];
181
grub_uint8_t symlink[(GRUB_UFS_DIRBLKS + GRUB_UFS_INDIRBLKS) * 4];
184
grub_uint32_t nblocks;
186
grub_uint32_t unused;
187
grub_uint8_t pad[12];
188
} __attribute__ ((packed));
191
177
/* Directory entry. */
192
178
struct grub_ufs_dirent
237
233
blk -= GRUB_UFS_DIRBLKS;
239
indirsz = UFS_BLKSZ (sblock) / INODE_BLKSZ;
235
indirsz = UFS_BLKSZ (sblock) / INODE_BLKSZ (data);
240
236
/* Single indirect block. */
241
237
if (blk < indirsz)
244
grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)];
246
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
239
grub_uint32_t indir[UFS_BLKSZ (sblock) >> 2];
248
240
grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 0) << log2_blksz,
249
241
0, sizeof (indir), indir);
242
return (data->ufs_type == UFS1) ? indir[blk] : indir[blk << 1];
254
246
/* Double indirect block. */
255
247
if (blk < indirsz * indirsz)
258
grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)];
260
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
249
grub_uint32_t indir[UFS_BLKSZ (sblock) >> 2];
263
251
grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 1) << log2_blksz,
264
252
0, sizeof (indir), indir);
265
253
grub_disk_read (data->disk,
266
(indir [blk / indirsz])
254
((data->ufs_type == UFS1) ?
255
indir[blk / indirsz] : indir [(blk / indirsz) << 1])
268
257
0, sizeof (indir), indir);
270
return indir[blk % indirsz];
259
return (data->ufs_type == UFS1) ?
260
indir[blk % indirsz] : indir[(blk % indirsz) << 1];
292
282
/* Adjust len so it we can't read past the end of the file. */
293
if (len + pos > INODE_SIZE (data))
294
len = INODE_SIZE (data) - pos;
283
if (len > INODE_SIZE (data))
284
len = INODE_SIZE (data);
296
286
blockcnt = (len + pos + UFS_BLKSZ (sblock) - 1) / UFS_BLKSZ (sblock);
360
351
/* The first block of the group. */
361
352
int grpblk = group * (grub_le_to_cpu32 (sblock->frags_per_group));
364
grpblk += grub_le_to_cpu32 (sblock->cylg_offset)
365
* (group & (~grub_le_to_cpu32 (sblock->cylg_mask)));
370
inode = (char *) &data->inode;
374
grub_disk_read (data->disk,
375
((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk)
376
<< grub_le_to_cpu32 (data->sblock.log2_blksz))
377
+ grpino / UFS_INODE_PER_BLOCK,
378
(grpino % UFS_INODE_PER_BLOCK)
379
* sizeof (struct grub_ufs_inode),
380
sizeof (struct grub_ufs_inode),
354
if (data->ufs_type == UFS1)
358
inode = (char *) &data->inode;
362
grub_disk_read (data->disk,
363
(((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk)
364
<< grub_le_to_cpu32 (data->sblock.log2_blksz)))
366
(grpino % 4) * sizeof (struct grub_ufs_inode),
367
sizeof (struct grub_ufs_inode),
374
inode = (char *) &data->inode2;
378
grub_disk_read (data->disk,
379
(((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk)
380
<< grub_le_to_cpu32 (data->sblock.log2_blksz)))
382
(grpino % 2) * sizeof (struct grub_ufs2_inode),
383
sizeof (struct grub_ufs2_inode),
383
387
return grub_errno;
462
466
(char *) &dirent) < 0)
463
467
return grub_errno;
466
namelen = dirent.namelen_bsd;
468
namelen = grub_le_to_cpu16 (dirent.namelen);
469
namelen = (data->ufs_type == UFS2)
470
? dirent.namelen_bsd : grub_le_to_cpu16 (dirent.namelen);
471
473
char filename[namelen + 1];
531
/* Find a UFS sblock. */
533
/* Find a UFS1 or UFS2 sblock. */
534
data->ufs_type = UNKNOWN;
532
535
while (*sblklist != -1)
534
537
grub_disk_read (disk, *sblklist, 0, sizeof (struct grub_ufs_sblock),
539
542
if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC)
544
data->ufs_type = UFS1;
547
else if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS2_MAGIC)
549
data->ufs_type = UFS2;
554
if (data->ufs_type == UNKNOWN)
556
grub_error (GRUB_ERR_BAD_FS, "not an ufs filesystem");
550
if (grub_errno == GRUB_ERR_NONE || grub_errno == GRUB_ERR_OUT_OF_RANGE)
553
grub_error (GRUB_ERR_BAD_FS, "not an ufs2 filesystem");
555
grub_error (GRUB_ERR_BAD_FS, "not an ufs1 filesystem");
559
565
grub_free (data);
567
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
568
grub_error (GRUB_ERR_BAD_FS, "not a ufs filesystem");
606
615
(char *) &dirent) < 0)
610
namelen = dirent.namelen_bsd;
612
namelen = grub_le_to_cpu16 (dirent.namelen);
618
namelen = (data->ufs_type == UFS2)
619
? dirent.namelen_bsd : grub_le_to_cpu16 (dirent.namelen);
616
622
char filename[namelen + 1];
617
623
struct grub_dirhook_info info;
618
struct grub_ufs_inode inode;
620
624
grub_memset (&info, 0, sizeof (info));
622
626
if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
626
630
filename[namelen] = '\0';
627
grub_ufs_read_inode (data, dirent.ino, (char *) &inode);
629
info.dir = ((grub_le_to_cpu16 (inode.mode) & GRUB_UFS_ATTR_TYPE)
630
== GRUB_UFS_ATTR_DIR);
631
info.mtime = grub_le_to_cpu64 (inode.mtime);
631
if (data->ufs_type == UFS1)
633
struct grub_ufs_inode inode;
634
grub_ufs_read_inode (data, dirent.ino, (char *) &inode);
635
info.dir = ((grub_le_to_cpu16 (inode.mode) & GRUB_UFS_ATTR_TYPE)
636
== GRUB_UFS_ATTR_DIR);
637
info.mtime = grub_le_to_cpu64 (inode.mtime);
642
struct grub_ufs2_inode inode;
643
grub_ufs_read_inode (data, dirent.ino, (char *) &inode);
644
info.dir = ((grub_le_to_cpu16 (inode.mode) & GRUB_UFS_ATTR_TYPE)
645
== GRUB_UFS_ATTR_DIR);
646
info.mtime = grub_le_to_cpu64 (inode.mtime);
634
650
if (hook (filename, &info))
731
748
grub_dl_ref (my_mod);
733
750
data = grub_ufs_mount (disk);
734
if (data && (data->sblock.uuidhi != 0 || data->sblock.uuidlow != 0))
736
753
*uuid = grub_malloc (16 + sizeof ('\0'));
737
754
grub_sprintf (*uuid, "%08x%08x",
760
777
data = grub_ufs_mount (device->disk);
780
else if (data->ufs_type == UFS1)
781
*tm = grub_le_to_cpu32 (data->sblock.mtime);
765
783
*tm = grub_le_to_cpu64 (data->sblock.mtime2);
767
*tm = grub_le_to_cpu32 (data->sblock.mtime);
770
785
grub_dl_unref (my_mod);