New developer version 0.6.8; added select () function; added demonstrating example...
[ZeXOS.git] / kernel / core / partition.c
blob94d7c9e6fa7305c6a3073e5922be7fdf241c825f
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program 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 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <system.h>
22 #include <string.h>
23 #include <dev.h>
24 #include <partition.h>
25 #include <fs.h>
26 #include <vfs.h>
28 partition_t partition_list;
29 extern vfs_t vfs_list;
31 partition_t *partition_find (char *name)
33 partition_t *partition;
34 for (partition = partition_list.next; partition != &partition_list; partition = partition->next) {
35 if (!strcmp (partition->name, name))
36 return partition;
39 return 0;
42 /* limited only for _one_ partition per device */
43 partition_t *partition_findbydev (dev_t *dev)
45 unsigned l = strlen (dev->devname);
47 partition_t *partition;
48 for (partition = partition_list.next; partition != &partition_list; partition = partition->next) {
49 if (!strncmp (partition->name, dev->devname, l))
50 return partition;
53 return 0;
56 /* find partition by file in current directory */
57 partition_t *partition_findbyfile (char *file)
59 char pwd[64];
60 strcpy (pwd, (char *) env_get ("PWD"));
62 vfs_t *vfs;
63 for (vfs = vfs_list.next; vfs != &vfs_list; vfs = vfs->next)
64 //printf ("pwd: %s : %s\n", vfs->mountpoint, pwd);
65 if (!strcmp (vfs->mountpoint, pwd) &&
66 !cstrcmp (file, vfs->name)) {
67 if (vfs->attrib & VFS_FILEATTR_DIR) {
68 printf ("ERROR -> this is a directory, not an file\n");
69 return 0;
72 /* check permissions */
73 if (vfs->attrib & VFS_FILEATTR_SYSTEM && strcmp ((char *) env_get ("USER"), "root")) {
74 printf ("ERROR -> only root can do that\n");
75 return 0;
78 if (vfs->attrib & VFS_FILEATTR_MOUNTED) {
79 partition_t *p = (partition_t *) mount_find ((char *) env_get ("PWD"));
81 if (p)
82 return p;
83 else {
84 printf ("ERROR -> device not respond\n");
85 return 0;
89 env_set ("PWD", pwd);
91 return 0;
94 printf ("No such file : %s\n", file);
96 return 0;
99 partition_t *partition_add (dev_t *dev, fs_t *fs, unsigned sector)
101 if (!dev)
102 return 0;
104 char name[20];
105 unsigned i;
106 for (i = 0; i < 256; i ++) {
107 sprintf (name, "%s%u", dev->devname, i);
109 if (partition_find (name) == 0)
110 break;
113 kprintf ("-> %s\n", name);
115 partition_t *partition;
117 /* alloc and init context */
118 partition = (partition_t *) kmalloc (sizeof (partition_t));
120 if (!partition)
121 return 0;
123 memset (partition, 0, sizeof (partition_t));
125 strcpy (partition->name, name);
127 partition->id = i;
129 /* check for hd'c' name - hda, hdb are pair of first cable; hdc, hdb are pair of second cable */
130 if (strlen (dev->devname) > 7) {
131 if (dev->devname[7] < 'c')
132 partition->base_io = 0x1F0;
133 else
134 partition->base_io = 0x170;
135 } else
136 partition->base_io = 0;
138 if (!fs)
139 partition->fs = (fs_t *) fs_detect (partition);
140 else
141 partition->fs = fs;
143 if (!partition->fs) {
144 kfree (partition);
145 return 0;
148 /* first partition sector on hdd */
149 partition->sector_start = sector;
151 if (!partition->fs->handler) {
152 kprintf ("ERROR -> fs handler is missing !\n");
153 kfree (partition);
154 return 0;
157 if (!partition->fs->handler (FS_ACT_INIT, (char *) partition, NULL, NULL)) {
158 kfree (partition);
159 return 0;
162 /* add into list */
163 partition->next = &partition_list;
164 partition->prev = partition_list.prev;
165 partition->prev->next = partition;
166 partition->next->prev = partition;
168 return partition;
171 bool partition_del (partition_t *partition)
173 if (partition) {
174 partition->next->prev = partition->prev;
175 partition->prev->next = partition->next;
177 //kfree (vfs);
178 return 1;
181 return 0;
184 unsigned partition_table (dev_t *dev)
186 unsigned char block[512];
188 if (!dev)
189 return 0;
191 unsigned l = strlen (dev->devname);
193 if (l < 8)
194 return 0;
196 partition_t p;
197 p.base_io = 0;
199 switch (dev->devname[7]) {
200 case 'a':
201 p.id = 0;
202 p.base_io = 0x1F0;
203 break;
204 case 'b':
205 p.id = 1;
206 p.base_io = 0x1F0;
207 break;
208 case 'c':
209 p.id = 0;
210 p.base_io = 0x170;
211 break;
212 case 'd':
213 p.id = 1;
214 p.base_io = 0x170;
215 break;
218 /* read first sector from drive */
219 if (!dev->handler (DEV_ACT_READ, &p, block, "", 0))
220 return 0;
222 unsigned i;
223 for (i = 0; i < 4; i ++) {
224 /* calculate MBR partition table address */
225 ptable_t *table = (ptable_t *) ((void *) block + 446 + i * sizeof (ptable_t));
227 if (!table->type)
228 break;
230 kprintf ("-> partition type %x - 0x%x (%d)\n", table->type, table->lba, table->blocks);
232 partition_t *pnew = 0;
234 switch (table->type) {
235 case 0x83:
236 pnew = partition_add (dev, fs_supported ("ext2"), table->lba);
237 break;
238 case 0x90:
239 pnew = partition_add (dev, fs_supported ("zexfs"), table->lba);
240 break;
244 return 1;
247 unsigned partition_table_new (dev_t *dev, ptable_t *ntable)
249 unsigned char block[512];
251 if (!dev)
252 return 0;
254 unsigned l = strlen (dev->devname);
256 if (l < 8)
257 return 0;
259 partition_t p;
260 p.base_io = 0;
262 switch (dev->devname[7]) {
263 case 'a':
264 p.id = 0;
265 p.base_io = 0x1F0;
266 break;
267 case 'b':
268 p.id = 1;
269 p.base_io = 0x1F0;
270 break;
271 case 'c':
272 p.id = 0;
273 p.base_io = 0x170;
274 break;
275 case 'd':
276 p.id = 1;
277 p.base_io = 0x170;
278 break;
281 /* read first sector from drive */
282 if (!dev->handler (DEV_ACT_READ, &p, block, "", 0))
283 return 0;
285 unsigned i;
286 for (i = 0; i < 4; i ++) {
287 /* calculate MBR partition table address */
288 ptable_t *table = (ptable_t *) ((void *) block + 446 + i * sizeof (ptable_t));
290 /* when partition type is filled, rewrite old entry */
291 if (ntable[i].type)
292 memcpy (table, &ntable[i], sizeof (ptable_t));
293 else
294 memcpy (&ntable[i], table, sizeof (ptable_t));
296 DPRINT (DBG_FS, "-> partition type %x - 0x%x (%d)", table->type, table->lba, table->blocks);
299 /* write into first sector of drive */
300 if (!dev->handler (DEV_ACT_WRITE, &p, block, "", 0))
301 return 0;
303 return 1;
306 unsigned int init_partition ()
308 partition_list.next = &partition_list;
309 partition_list.prev = &partition_list;
311 return 1;