1 /* btrfs.c - B-tree file system.  */
2 /*
3  *  GRUB  --  GRand Unified Bootloader
4  *  Copyright (C) 2010  Free Software Foundation, Inc.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19 
20 #include <grub/err.h>
21 #include <grub/file.h>
22 #include <grub/mm.h>
23 #include <grub/misc.h>
24 #include <grub/disk.h>
25 #include <grub/types.h>
26 #include <r_types.h>
27 #define BTRFS_SIGNATURE "_BHRfS_M"
28 R_PACKED(
29 struct btrfs_superblock
30 {
31   grub_uint8_t dummy1[32];
32   grub_uint16_t uuid[8];
33   grub_uint8_t dummy2[16];
34   grub_uint8_t signature[sizeof (BTRFS_SIGNATURE) - 1];
35 });
36 
37 struct grub_btrfs_data
38 {
39   struct btrfs_superblock sblock;
40 };
41 
42 static struct grub_btrfs_data *
grub_btrfs_mount(grub_disk_t disk)43 grub_btrfs_mount (grub_disk_t disk)
44 {
45   struct grub_btrfs_data *data = grub_malloc (sizeof (*data));
46   if (! data)
47     return NULL;
48 
49   if (grub_disk_read (disk, 128, 0, sizeof (data->sblock),
50 		      &data->sblock) != GRUB_ERR_NONE)
51     goto fail;
52 
53   if (grub_memcmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1))
54     {
55       grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem");
56       goto fail;
57     }
58 
59   return data;
60 
61  fail:
62   grub_free (data);
63   return NULL;
64 }
65 
66 static grub_err_t
grub_btrfs_open(struct grub_file * file,const char * name)67 grub_btrfs_open (struct grub_file *file ,
68 		 const char *name )
69 {
70   return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "only detection is supported for Btrfs");
71 }
72 
73 static grub_err_t
grub_btrfs_dir(grub_device_t device,const char * path,int (* hook)(const char * filename,const struct grub_dirhook_info * info))74 grub_btrfs_dir (grub_device_t device,
75                 const char *path ,
76                 int (*hook) (const char *filename,
77                              const struct grub_dirhook_info *info))
78 {
79   struct grub_btrfs_data *data = grub_btrfs_mount (device->disk);
80   if (grub_errno)
81     return grub_errno;
82 // TODO: no hook here? wtf?
83   grub_free (data);
84 
85   return GRUB_ERR_NONE;
86 }
87 
88 static grub_err_t
grub_btrfs_uuid(grub_device_t device,char ** uuid)89 grub_btrfs_uuid (grub_device_t device, char **uuid)
90 {
91   struct grub_btrfs_data *data;
92 
93   *uuid = NULL;
94 
95   data = grub_btrfs_mount (device->disk);
96   if (! data)
97     return grub_errno;
98 
99   *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
100 			  grub_be_to_cpu16 (data->sblock.uuid[0]),
101 			  grub_be_to_cpu16 (data->sblock.uuid[1]),
102 			  grub_be_to_cpu16 (data->sblock.uuid[2]),
103 			  grub_be_to_cpu16 (data->sblock.uuid[3]),
104 			  grub_be_to_cpu16 (data->sblock.uuid[4]),
105 			  grub_be_to_cpu16 (data->sblock.uuid[5]),
106 			  grub_be_to_cpu16 (data->sblock.uuid[6]),
107 			  grub_be_to_cpu16 (data->sblock.uuid[7]));
108 
109   grub_free (data);
110 
111   return grub_errno;
112 }
113 
114 struct grub_fs grub_btrfs_fs =
115   {
116     .name = "btrfs",
117     .dir = grub_btrfs_dir,
118     .open = grub_btrfs_open,
119     .uuid = grub_btrfs_uuid,
120   };
121