1 /* nand.c - NAND flash disk access. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008 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/>.
20 #include <grub/misc.h>
21 #include <grub/disk.h>
24 #include <grub/ieee1275/ieee1275.h>
28 grub_ieee1275_ihandle_t handle
;
29 grub_uint32_t block_size
;
33 grub_nand_iterate (int (*hook
) (const char *name
))
35 auto int dev_iterate (struct grub_ieee1275_devalias
*alias
);
36 int dev_iterate (struct grub_ieee1275_devalias
*alias
)
38 if (! grub_strcmp (alias
->name
, "nand"))
47 grub_devalias_iterate (dev_iterate
);
52 grub_nand_read (grub_disk_t disk
, grub_disk_addr_t sector
,
53 grub_size_t size
, char *buf
);
56 grub_nand_open (const char *name
, grub_disk_t disk
)
58 grub_ieee1275_ihandle_t dev_ihandle
= 0;
59 struct grub_nand_data
*data
= 0;
62 struct grub_ieee1275_common_hdr common
;
64 grub_ieee1275_ihandle_t ihandle
;
65 grub_ieee1275_cell_t result
;
66 grub_ieee1275_cell_t size1
;
67 grub_ieee1275_cell_t size2
;
70 if (! grub_strstr (name
, "nand"))
71 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "Not a nand device");
73 data
= grub_malloc (sizeof (*data
));
77 grub_ieee1275_open (name
, &dev_ihandle
);
80 grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "Can't open device");
84 data
->handle
= dev_ihandle
;
86 INIT_IEEE1275_COMMON (&args
.common
, "call-method", 2, 2);
87 args
.method
= "block-size";
88 args
.ihandle
= dev_ihandle
;
91 if ((IEEE1275_CALL_ENTRY_FN (&args
) == -1) || (args
.result
))
93 grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "Can't get block size");
97 data
->block_size
= (args
.size1
>> GRUB_DISK_SECTOR_BITS
);
99 INIT_IEEE1275_COMMON (&args
.common
, "call-method", 2, 3);
100 args
.method
= "size";
101 args
.ihandle
= dev_ihandle
;
104 if ((IEEE1275_CALL_ENTRY_FN (&args
) == -1) || (args
.result
))
106 grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "Can't get disk size");
110 disk
->total_sectors
= args
.size1
;
111 disk
->total_sectors
<<= 32;
112 disk
->total_sectors
+= args
.size2
;
113 disk
->total_sectors
>>= GRUB_DISK_SECTOR_BITS
;
115 disk
->id
= dev_ihandle
;
117 disk
->has_partitions
= 0;
124 grub_ieee1275_close (dev_ihandle
);
130 grub_nand_close (grub_disk_t disk
)
132 grub_ieee1275_close (((struct grub_nand_data
*) disk
->data
)->handle
);
133 grub_free (disk
->data
);
137 grub_nand_read (grub_disk_t disk
, grub_disk_addr_t sector
,
138 grub_size_t size
, char *buf
)
140 struct grub_nand_data
*data
= disk
->data
;
141 grub_size_t bsize
, ofs
;
145 struct grub_ieee1275_common_hdr common
;
147 grub_ieee1275_ihandle_t ihandle
;
148 grub_ieee1275_cell_t ofs
;
149 grub_ieee1275_cell_t page
;
150 grub_ieee1275_cell_t len
;
151 grub_ieee1275_cell_t buf
;
152 grub_ieee1275_cell_t result
;
155 INIT_IEEE1275_COMMON (&args
.common
, "call-method", 6, 1);
156 args
.method
= "pio-read";
157 args
.ihandle
= data
->handle
;
158 args
.buf
= (grub_ieee1275_cell_t
) buf
;
159 args
.page
= (grub_ieee1275_cell_t
) ((grub_size_t
) sector
/ data
->block_size
);
161 ofs
= ((grub_size_t
) sector
% data
->block_size
) << GRUB_DISK_SECTOR_BITS
;
162 size
<<= GRUB_DISK_SECTOR_BITS
;
163 bsize
= (data
->block_size
<< GRUB_DISK_SECTOR_BITS
);
169 len
= (ofs
+ size
> bsize
) ? (bsize
- ofs
) : size
;
171 args
.len
= (grub_ieee1275_cell_t
) len
;
172 args
.ofs
= (grub_ieee1275_cell_t
) ofs
;
175 if ((IEEE1275_CALL_ENTRY_FN (&args
) == -1) || (args
.result
))
176 return grub_error (GRUB_ERR_READ_ERROR
, "Read error");
184 return GRUB_ERR_NONE
;
188 grub_nand_write (grub_disk_t disk
__attribute ((unused
)),
189 grub_disk_addr_t sector
__attribute ((unused
)),
190 grub_size_t size
__attribute ((unused
)),
191 const char *buf
__attribute ((unused
)))
193 return GRUB_ERR_NOT_IMPLEMENTED_YET
;
196 static struct grub_disk_dev grub_nand_dev
=
199 .id
= GRUB_DISK_DEVICE_NAND_ID
,
200 .iterate
= grub_nand_iterate
,
201 .open
= grub_nand_open
,
202 .close
= grub_nand_close
,
203 .read
= grub_nand_read
,
204 .write
= grub_nand_write
,
210 grub_disk_dev_register (&grub_nand_dev
);
215 grub_disk_dev_unregister (&grub_nand_dev
);