3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/file.h>
23 #include <grub/misc.h>
24 #include <grub/disk.h>
26 #include <grub/types.h>
27 #include <grub/fshelp.h>
29 GRUB_MOD_LICENSE ("GPLv3+");
31 #define XFS_INODE_EXTENTS 9
33 #define XFS_INODE_FORMAT_INO 1
34 #define XFS_INODE_FORMAT_EXT 2
35 #define XFS_INODE_FORMAT_BTREE 3
38 struct grub_xfs_sblock
40 grub_uint8_t magic
[4];
42 grub_uint8_t unused1
[24];
43 grub_uint16_t uuid
[8];
44 grub_uint8_t unused2
[8];
45 grub_uint64_t rootino
;
46 grub_uint8_t unused3
[20];
48 grub_uint8_t unused4
[20];
49 grub_uint8_t label
[12];
50 grub_uint8_t log2_bsize
;
51 grub_uint8_t log2_sect
;
52 grub_uint8_t log2_inode
;
53 grub_uint8_t log2_inop
;
54 grub_uint8_t log2_agblk
;
55 grub_uint8_t unused6
[67];
56 grub_uint8_t log2_dirblk
;
59 struct grub_xfs_dir_header
62 grub_uint8_t smallino
;
70 struct grub_xfs_dir_entry
75 /* Inode number follows, 32 bits. */
78 struct grub_xfs_dir2_entry
84 typedef grub_uint32_t grub_xfs_extent
[4];
86 struct grub_xfs_btree_node
88 grub_uint8_t magic
[4];
90 grub_uint16_t numrecs
;
93 grub_uint64_t keys
[1];
96 struct grub_xfs_btree_root
99 grub_uint16_t numrecs
;
100 grub_uint64_t keys
[1];
106 grub_uint32_t nanosec
;
109 struct grub_xfs_inode
111 grub_uint8_t magic
[2];
113 grub_uint8_t version
;
115 grub_uint8_t unused2
[26];
116 struct grub_xfs_time atime
;
117 struct grub_xfs_time mtime
;
118 struct grub_xfs_time ctime
;
120 grub_uint64_t nblocks
;
121 grub_uint32_t extsize
;
122 grub_uint32_t nextents
;
123 grub_uint16_t unused3
;
124 grub_uint8_t fork_offset
;
125 grub_uint8_t unused4
[17];
131 struct grub_xfs_dir_header dirhead
;
132 struct grub_xfs_dir_entry direntry
[1];
134 grub_xfs_extent extents
[XFS_INODE_EXTENTS
];
135 struct grub_xfs_btree_root btree
;
139 struct grub_xfs_dirblock_tail
141 grub_uint32_t leaf_count
;
142 grub_uint32_t leaf_stale
;
145 struct grub_fshelp_node
147 struct grub_xfs_data
*data
;
150 struct grub_xfs_inode inode
;
155 struct grub_xfs_sblock sblock
;
159 grub_uint32_t agsize
;
160 struct grub_fshelp_node diropen
;
163 static grub_dl_t my_mod
;
167 /* Filetype information as used in inodes. */
168 #define FILETYPE_INO_MASK 0170000
169 #define FILETYPE_INO_REG 0100000
170 #define FILETYPE_INO_DIRECTORY 0040000
171 #define FILETYPE_INO_SYMLINK 0120000
174 GRUB_XFS_INO_AGBITS(struct grub_xfs_data
*data
)
176 return ((data
)->sblock
.log2_agblk
+ (data
)->sblock
.log2_inop
);
179 static inline grub_uint64_t
180 GRUB_XFS_INO_INOINAG (struct grub_xfs_data
*data
,
183 return (grub_be_to_cpu64 (ino
) & ((1LL << GRUB_XFS_INO_AGBITS (data
)) - 1));
186 static inline grub_uint64_t
187 GRUB_XFS_INO_AG (struct grub_xfs_data
*data
,
190 return (grub_be_to_cpu64 (ino
) >> GRUB_XFS_INO_AGBITS (data
));
193 static inline grub_disk_addr_t
194 GRUB_XFS_FSB_TO_BLOCK (struct grub_xfs_data
*data
, grub_disk_addr_t fsb
)
196 return ((fsb
>> data
->sblock
.log2_agblk
) * data
->agsize
197 + (fsb
& ((1LL << data
->sblock
.log2_agblk
) - 1)));
200 static inline grub_uint64_t
201 GRUB_XFS_EXTENT_OFFSET (grub_xfs_extent
*exts
, int ex
)
203 return ((grub_be_to_cpu32 (exts
[ex
][0]) & ~(1 << 31)) << 23
204 | grub_be_to_cpu32 (exts
[ex
][1]) >> 9);
207 static inline grub_uint64_t
208 GRUB_XFS_EXTENT_BLOCK (grub_xfs_extent
*exts
, int ex
)
210 return ((grub_uint64_t
) (grub_be_to_cpu32 (exts
[ex
][1])
212 | (grub_uint64_t
) grub_be_to_cpu32 (exts
[ex
][2]) << 11
213 | grub_be_to_cpu32 (exts
[ex
][3]) >> 21);
216 static inline grub_uint64_t
217 GRUB_XFS_EXTENT_SIZE (grub_xfs_extent
*exts
, int ex
)
219 return (grub_be_to_cpu32 (exts
[ex
][3]) & ((1 << 21) - 1));
223 GRUB_XFS_ROUND_TO_DIRENT (int pos
)
225 return ((((pos
) + 8 - 1) / 8) * 8);
229 GRUB_XFS_NEXT_DIRENT (int pos
, int len
)
231 return (pos
) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len
+ 2);
235 static inline grub_uint64_t
236 grub_xfs_inode_block (struct grub_xfs_data
*data
,
239 long long int inoinag
= GRUB_XFS_INO_INOINAG (data
, ino
);
240 long long ag
= GRUB_XFS_INO_AG (data
, ino
);
243 block
= (inoinag
>> data
->sblock
.log2_inop
) + ag
* data
->agsize
;
244 block
<<= (data
->sblock
.log2_bsize
- GRUB_DISK_SECTOR_BITS
);
250 grub_xfs_inode_offset (struct grub_xfs_data
*data
,
253 int inoag
= GRUB_XFS_INO_INOINAG (data
, ino
);
254 return ((inoag
& ((1 << data
->sblock
.log2_inop
) - 1)) <<
255 data
->sblock
.log2_inode
);
260 grub_xfs_read_inode (struct grub_xfs_data
*data
, grub_uint64_t ino
,
261 struct grub_xfs_inode
*inode
)
263 grub_uint64_t block
= grub_xfs_inode_block (data
, ino
);
264 int offset
= grub_xfs_inode_offset (data
, ino
);
266 /* Read the inode. */
267 if (grub_disk_read (data
->disk
, block
, offset
,
268 1 << data
->sblock
.log2_inode
, inode
))
271 if (grub_strncmp ((char *) inode
->magic
, "IN", 2))
272 return grub_error (GRUB_ERR_BAD_FS
, "not a correct XFS inode");
278 static grub_disk_addr_t
279 grub_xfs_read_block (grub_fshelp_node_t node
, grub_disk_addr_t fileblock
)
281 struct grub_xfs_btree_node
*leaf
= 0;
283 grub_xfs_extent
*exts
;
284 grub_uint64_t ret
= 0;
286 if (node
->inode
.format
== XFS_INODE_FORMAT_BTREE
)
288 const grub_uint64_t
*keys
;
291 leaf
= grub_malloc (node
->data
->bsize
);
295 nrec
= grub_be_to_cpu16 (node
->inode
.data
.btree
.numrecs
);
296 keys
= &node
->inode
.data
.btree
.keys
[0];
297 if (node
->inode
.fork_offset
)
298 recoffset
= (node
->inode
.fork_offset
- 1) / 2;
300 recoffset
= ((1 << node
->data
->sblock
.log2_inode
)
301 - ((char *) &node
->inode
.data
.btree
.keys
302 - (char *) &node
->inode
))
303 / (2 * sizeof (grub_uint64_t
));
308 for (i
= 0; i
< nrec
; i
++)
310 if (fileblock
< grub_be_to_cpu64 (keys
[i
]))
320 if (grub_disk_read (node
->data
->disk
,
321 GRUB_XFS_FSB_TO_BLOCK (node
->data
, grub_be_to_cpu64 (keys
[i
- 1 + recoffset
])) << (node
->data
->sblock
.log2_bsize
- GRUB_DISK_SECTOR_BITS
),
322 0, node
->data
->bsize
, leaf
))
325 if (grub_strncmp ((char *) leaf
->magic
, "BMAP", 4))
328 grub_error (GRUB_ERR_BAD_FS
, "not a correct XFS BMAP node");
332 nrec
= grub_be_to_cpu16 (leaf
->numrecs
);
333 keys
= &leaf
->keys
[0];
334 recoffset
= ((node
->data
->bsize
- ((char *) &leaf
->keys
336 / (2 * sizeof (grub_uint64_t
)));
339 exts
= (grub_xfs_extent
*) keys
;
341 else if (node
->inode
.format
== XFS_INODE_FORMAT_EXT
)
343 nrec
= grub_be_to_cpu32 (node
->inode
.nextents
);
344 exts
= &node
->inode
.data
.extents
[0];
348 grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
349 "XFS does not support inode format %d yet",
354 /* Iterate over each extent to figure out which extent has
355 the block we are looking for. */
356 for (ex
= 0; ex
< nrec
; ex
++)
358 grub_uint64_t start
= GRUB_XFS_EXTENT_BLOCK (exts
, ex
);
359 grub_uint64_t offset
= GRUB_XFS_EXTENT_OFFSET (exts
, ex
);
360 grub_uint64_t size
= GRUB_XFS_EXTENT_SIZE (exts
, ex
);
363 if (fileblock
< offset
)
365 else if (fileblock
< offset
+ size
)
367 ret
= (fileblock
- offset
+ start
);
374 return GRUB_XFS_FSB_TO_BLOCK(node
->data
, ret
);
378 /* Read LEN bytes from the file described by DATA starting with byte
379 POS. Return the amount of read bytes in READ. */
381 grub_xfs_read_file (grub_fshelp_node_t node
,
382 grub_disk_read_hook_t read_hook
, void *read_hook_data
,
383 grub_off_t pos
, grub_size_t len
, char *buf
)
385 return grub_fshelp_read_file (node
->data
->disk
, node
,
386 read_hook
, read_hook_data
,
387 pos
, len
, buf
, grub_xfs_read_block
,
388 grub_be_to_cpu64 (node
->inode
.size
),
389 node
->data
->sblock
.log2_bsize
390 - GRUB_DISK_SECTOR_BITS
, 0);
395 grub_xfs_read_symlink (grub_fshelp_node_t node
)
397 int size
= grub_be_to_cpu64 (node
->inode
.size
);
399 switch (node
->inode
.format
)
401 case XFS_INODE_FORMAT_INO
:
402 return grub_strndup (node
->inode
.data
.raw
, size
);
404 case XFS_INODE_FORMAT_EXT
:
407 grub_ssize_t numread
;
409 symlink
= grub_malloc (size
+ 1);
413 numread
= grub_xfs_read_file (node
, 0, 0, 0, size
, symlink
);
419 symlink
[size
] = '\0';
428 static enum grub_fshelp_filetype
429 grub_xfs_mode_to_filetype (grub_uint16_t mode
)
431 if ((grub_be_to_cpu16 (mode
)
432 & FILETYPE_INO_MASK
) == FILETYPE_INO_DIRECTORY
)
433 return GRUB_FSHELP_DIR
;
434 else if ((grub_be_to_cpu16 (mode
)
435 & FILETYPE_INO_MASK
) == FILETYPE_INO_SYMLINK
)
436 return GRUB_FSHELP_SYMLINK
;
437 else if ((grub_be_to_cpu16 (mode
)
438 & FILETYPE_INO_MASK
) == FILETYPE_INO_REG
)
439 return GRUB_FSHELP_REG
;
440 return GRUB_FSHELP_UNKNOWN
;
444 /* Context for grub_xfs_iterate_dir. */
445 struct grub_xfs_iterate_dir_ctx
447 grub_fshelp_iterate_dir_hook_t hook
;
449 struct grub_fshelp_node
*diro
;
452 /* Helper for grub_xfs_iterate_dir. */
453 static int iterate_dir_call_hook (grub_uint64_t ino
, const char *filename
,
454 struct grub_xfs_iterate_dir_ctx
*ctx
)
456 struct grub_fshelp_node
*fdiro
;
459 fdiro
= grub_malloc (sizeof (struct grub_fshelp_node
)
460 - sizeof (struct grub_xfs_inode
)
461 + (1 << ctx
->diro
->data
->sblock
.log2_inode
) + 1);
468 /* The inode should be read, otherwise the filetype can
469 not be determined. */
471 fdiro
->inode_read
= 1;
472 fdiro
->data
= ctx
->diro
->data
;
473 err
= grub_xfs_read_inode (ctx
->diro
->data
, ino
, &fdiro
->inode
);
480 return ctx
->hook (filename
, grub_xfs_mode_to_filetype (fdiro
->inode
.mode
),
481 fdiro
, ctx
->hook_data
);
485 grub_xfs_iterate_dir (grub_fshelp_node_t dir
,
486 grub_fshelp_iterate_dir_hook_t hook
, void *hook_data
)
488 struct grub_fshelp_node
*diro
= (struct grub_fshelp_node
*) dir
;
489 struct grub_xfs_iterate_dir_ctx ctx
= {
491 .hook_data
= hook_data
,
495 switch (diro
->inode
.format
)
497 case XFS_INODE_FORMAT_INO
:
499 struct grub_xfs_dir_entry
*de
= &diro
->inode
.data
.dir
.direntry
[0];
500 int smallino
= !diro
->inode
.data
.dir
.dirhead
.smallino
;
502 grub_uint64_t parent
;
504 /* If small inode numbers are used to pack the direntry, the
505 parent inode number is small too. */
508 parent
= grub_be_to_cpu32 (diro
->inode
.data
.dir
.dirhead
.parent
.i4
);
509 parent
= grub_cpu_to_be64 (parent
);
510 /* The header is a bit smaller than usual. */
511 de
= (struct grub_xfs_dir_entry
*) ((char *) de
- 4);
515 parent
= diro
->inode
.data
.dir
.dirhead
.parent
.i8
;
518 /* Synthesize the direntries for `.' and `..'. */
519 if (iterate_dir_call_hook (diro
->ino
, ".", &ctx
))
522 if (iterate_dir_call_hook (parent
, "..", &ctx
))
525 for (i
= 0; i
< diro
->inode
.data
.dir
.dirhead
.count
; i
++)
528 grub_uint8_t
*inopos
= (((grub_uint8_t
*) de
)
529 + sizeof (struct grub_xfs_dir_entry
)
533 /* inopos might be unaligned. */
535 ino
= (((grub_uint32_t
) inopos
[0]) << 24)
536 | (((grub_uint32_t
) inopos
[1]) << 16)
537 | (((grub_uint32_t
) inopos
[2]) << 8)
538 | (((grub_uint32_t
) inopos
[3]) << 0);
540 ino
= (((grub_uint64_t
) inopos
[0]) << 56)
541 | (((grub_uint64_t
) inopos
[1]) << 48)
542 | (((grub_uint64_t
) inopos
[2]) << 40)
543 | (((grub_uint64_t
) inopos
[3]) << 32)
544 | (((grub_uint64_t
) inopos
[4]) << 24)
545 | (((grub_uint64_t
) inopos
[5]) << 16)
546 | (((grub_uint64_t
) inopos
[6]) << 8)
547 | (((grub_uint64_t
) inopos
[7]) << 0);
548 ino
= grub_cpu_to_be64 (ino
);
550 c
= de
->name
[de
->len
];
551 de
->name
[de
->len
] = '\0';
552 if (iterate_dir_call_hook (ino
, de
->name
, &ctx
))
554 de
->name
[de
->len
] = c
;
556 de
= ((struct grub_xfs_dir_entry
*)
557 (((char *) de
)+ sizeof (struct grub_xfs_dir_entry
) + de
->len
558 + ((smallino
? sizeof (grub_uint32_t
)
559 : sizeof (grub_uint64_t
))) - 1));
564 case XFS_INODE_FORMAT_BTREE
:
565 case XFS_INODE_FORMAT_EXT
:
567 grub_ssize_t numread
;
570 int dirblk_size
, dirblk_log2
;
572 dirblk_log2
= (dir
->data
->sblock
.log2_bsize
573 + dir
->data
->sblock
.log2_dirblk
);
574 dirblk_size
= 1 << dirblk_log2
;
576 dirblock
= grub_malloc (dirblk_size
);
580 /* Iterate over every block the directory has. */
582 blk
< (grub_be_to_cpu64 (dir
->inode
.size
)
586 /* The header is skipped, the first direntry is stored
590 int tail_start
= (dirblk_size
591 - sizeof (struct grub_xfs_dirblock_tail
));
593 struct grub_xfs_dirblock_tail
*tail
;
594 tail
= (struct grub_xfs_dirblock_tail
*) &dirblock
[tail_start
];
596 numread
= grub_xfs_read_file (dir
, 0, 0,
598 dirblk_size
, dirblock
);
599 if (numread
!= dirblk_size
)
602 entries
= (grub_be_to_cpu32 (tail
->leaf_count
)
603 - grub_be_to_cpu32 (tail
->leaf_stale
));
605 /* Iterate over all entries within this block. */
606 while (pos
< (dirblk_size
607 - (int) sizeof (struct grub_xfs_dir2_entry
)))
609 struct grub_xfs_dir2_entry
*direntry
;
610 grub_uint8_t
*freetag
;
613 direntry
= (struct grub_xfs_dir2_entry
*) &dirblock
[pos
];
614 freetag
= (grub_uint8_t
*) direntry
;
616 if (grub_get_unaligned16 (freetag
) == 0XFFFF)
618 grub_uint8_t
*skip
= (freetag
+ sizeof (grub_uint16_t
));
620 /* This entry is not used, go to the next one. */
621 pos
+= grub_be_to_cpu16 (grub_get_unaligned16 (skip
));
626 filename
= &dirblock
[pos
+ sizeof (*direntry
)];
627 /* The byte after the filename is for the tag, which
628 is not used by GRUB. So it can be overwritten. */
629 filename
[direntry
->len
] = '\0';
631 if (iterate_dir_call_hook (direntry
->inode
, filename
, &ctx
))
633 grub_free (dirblock
);
637 /* Check if last direntry in this block is
643 /* Select the next directory entry. */
644 pos
= GRUB_XFS_NEXT_DIRENT (pos
, direntry
->len
);
645 pos
= GRUB_XFS_ROUND_TO_DIRENT (pos
);
648 grub_free (dirblock
);
653 grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
654 "XFS does not support inode format %d yet",
661 static struct grub_xfs_data
*
662 grub_xfs_mount (grub_disk_t disk
)
664 struct grub_xfs_data
*data
= 0;
666 data
= grub_zalloc (sizeof (struct grub_xfs_data
));
670 /* Read the superblock. */
671 if (grub_disk_read (disk
, 0, 0,
672 sizeof (struct grub_xfs_sblock
), &data
->sblock
))
675 if (grub_strncmp ((char *) (data
->sblock
.magic
), "XFSB", 4)
676 || data
->sblock
.log2_bsize
< GRUB_DISK_SECTOR_BITS
677 || ((int) data
->sblock
.log2_bsize
678 + (int) data
->sblock
.log2_dirblk
) >= 27)
680 grub_error (GRUB_ERR_BAD_FS
, "not a XFS filesystem");
684 data
= grub_realloc (data
,
685 sizeof (struct grub_xfs_data
)
686 - sizeof (struct grub_xfs_inode
)
687 + (1 << data
->sblock
.log2_inode
) + 1);
692 data
->diropen
.data
= data
;
693 data
->diropen
.ino
= data
->sblock
.rootino
;
694 data
->diropen
.inode_read
= 1;
695 data
->bsize
= grub_be_to_cpu32 (data
->sblock
.bsize
);
696 data
->agsize
= grub_be_to_cpu32 (data
->sblock
.agsize
);
701 grub_xfs_read_inode (data
, data
->diropen
.ino
, &data
->diropen
.inode
);
706 if (grub_errno
== GRUB_ERR_OUT_OF_RANGE
)
707 grub_error (GRUB_ERR_BAD_FS
, "not an XFS filesystem");
715 /* Context for grub_xfs_dir. */
716 struct grub_xfs_dir_ctx
718 grub_fs_dir_hook_t hook
;
722 /* Helper for grub_xfs_dir. */
724 grub_xfs_dir_iter (const char *filename
, enum grub_fshelp_filetype filetype
,
725 grub_fshelp_node_t node
, void *data
)
727 struct grub_xfs_dir_ctx
*ctx
= data
;
728 struct grub_dirhook_info info
;
730 grub_memset (&info
, 0, sizeof (info
));
731 if (node
->inode_read
)
734 info
.mtime
= grub_be_to_cpu32 (node
->inode
.mtime
.sec
);
736 info
.dir
= ((filetype
& GRUB_FSHELP_TYPE_MASK
) == GRUB_FSHELP_DIR
);
738 return ctx
->hook (filename
, &info
, ctx
->hook_data
);
742 grub_xfs_dir (grub_device_t device
, const char *path
,
743 grub_fs_dir_hook_t hook
, void *hook_data
)
745 struct grub_xfs_dir_ctx ctx
= { hook
, hook_data
};
746 struct grub_xfs_data
*data
= 0;
747 struct grub_fshelp_node
*fdiro
= 0;
749 grub_dl_ref (my_mod
);
751 data
= grub_xfs_mount (device
->disk
);
755 grub_fshelp_find_file (path
, &data
->diropen
, &fdiro
, grub_xfs_iterate_dir
,
756 grub_xfs_read_symlink
, GRUB_FSHELP_DIR
);
760 grub_xfs_iterate_dir (fdiro
, grub_xfs_dir_iter
, &ctx
);
763 if (fdiro
!= &data
->diropen
)
769 grub_dl_unref (my_mod
);
775 /* Open a file named NAME and initialize FILE. */
777 grub_xfs_open (struct grub_file
*file
, const char *name
)
779 struct grub_xfs_data
*data
;
780 struct grub_fshelp_node
*fdiro
= 0;
782 grub_dl_ref (my_mod
);
784 data
= grub_xfs_mount (file
->device
->disk
);
788 grub_fshelp_find_file (name
, &data
->diropen
, &fdiro
, grub_xfs_iterate_dir
,
789 grub_xfs_read_symlink
, GRUB_FSHELP_REG
);
793 if (!fdiro
->inode_read
)
795 grub_xfs_read_inode (data
, fdiro
->ino
, &fdiro
->inode
);
800 if (fdiro
!= &data
->diropen
)
802 grub_memcpy (&data
->diropen
, fdiro
,
803 sizeof (struct grub_fshelp_node
)
804 - sizeof (struct grub_xfs_inode
)
805 + (1 << data
->sblock
.log2_inode
));
809 file
->size
= grub_be_to_cpu64 (data
->diropen
.inode
.size
);
816 if (fdiro
!= &data
->diropen
)
821 grub_dl_unref (my_mod
);
828 grub_xfs_read (grub_file_t file
, char *buf
, grub_size_t len
)
830 struct grub_xfs_data
*data
=
831 (struct grub_xfs_data
*) file
->data
;
833 return grub_xfs_read_file (&data
->diropen
,
834 file
->read_hook
, file
->read_hook_data
,
835 file
->offset
, len
, buf
);
840 grub_xfs_close (grub_file_t file
)
842 grub_free (file
->data
);
844 grub_dl_unref (my_mod
);
846 return GRUB_ERR_NONE
;
851 grub_xfs_label (grub_device_t device
, char **label
)
853 struct grub_xfs_data
*data
;
854 grub_disk_t disk
= device
->disk
;
856 grub_dl_ref (my_mod
);
858 data
= grub_xfs_mount (disk
);
860 *label
= grub_strndup ((char *) (data
->sblock
.label
), 12);
864 grub_dl_unref (my_mod
);
872 grub_xfs_uuid (grub_device_t device
, char **uuid
)
874 struct grub_xfs_data
*data
;
875 grub_disk_t disk
= device
->disk
;
877 grub_dl_ref (my_mod
);
879 data
= grub_xfs_mount (disk
);
882 *uuid
= grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
883 grub_be_to_cpu16 (data
->sblock
.uuid
[0]),
884 grub_be_to_cpu16 (data
->sblock
.uuid
[1]),
885 grub_be_to_cpu16 (data
->sblock
.uuid
[2]),
886 grub_be_to_cpu16 (data
->sblock
.uuid
[3]),
887 grub_be_to_cpu16 (data
->sblock
.uuid
[4]),
888 grub_be_to_cpu16 (data
->sblock
.uuid
[5]),
889 grub_be_to_cpu16 (data
->sblock
.uuid
[6]),
890 grub_be_to_cpu16 (data
->sblock
.uuid
[7]));
895 grub_dl_unref (my_mod
);
904 static struct grub_fs grub_xfs_fs
=
908 .open
= grub_xfs_open
,
909 .read
= grub_xfs_read
,
910 .close
= grub_xfs_close
,
911 .label
= grub_xfs_label
,
912 .uuid
= grub_xfs_uuid
,
914 .reserved_first_sector
= 0,
915 .blocklist_install
= 1,
922 grub_fs_register (&grub_xfs_fs
);
928 grub_fs_unregister (&grub_xfs_fs
);