SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

001 /* Copyright (C) 2005  Thomas Petazzoni
002 
003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any later version.
007 
008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details.
012 
013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.
017 */
018 
019 #include <sos/kmalloc.h>
020 #include <sos/blkdev.h>
021 #include <drivers/bochs.h>
022 
023 /**
024  * This structure defines the structure of a partition entry
025  * (determined by the PC architecture)
026  */
027 typedef struct partition_entry
028 {
029   sos_ui8_t  active;
030   sos_ui8_t  start_dl;
031   sos_ui16_t start_cylinder;
032   sos_ui8_t  type;
033   sos_ui8_t  end_dl;
034   sos_ui16_t end_cylinder;
035   sos_ui32_t lba;
036   sos_ui32_t size;
037 } partition_entry_t;
038 
039 /**
040  * Offset of the partition table inside the 512-byte sector.
041  */
042 #define PART_TABLE_OFFSET 446
043 
044 /**
045  * The most common partition types. For a complete list, you can for
046  * example refer to
047  * http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
048  */
049 #define PART_TYPE_EXTENDED   0x5
050 #define PART_TYPE_FAT16_1    0xe
051 #define PART_TYPE_FAT16_2    0x6
052 #define PART_TYPE_FAT32_1    0xb
053 #define PART_TYPE_FAT32_2    0xc
054 #define PART_TYPE_LINUX_SWAP 0x82
055 #define PART_TYPE_LINUX      0x83
056 
057 /**
058  * Converts a partition type to a string
059  */
060 static const char *
061 sos_part_type_str (unsigned int type)
062 {
063   switch (type)
064     {
065     case PART_TYPE_EXTENDED:
066       return "Extended";
067     case PART_TYPE_FAT16_1:
068     case PART_TYPE_FAT16_2:
069       return "FAT16";
070     case PART_TYPE_FAT32_1:
071     case PART_TYPE_FAT32_2:
072       return "FAT32";
073     case PART_TYPE_LINUX_SWAP:
074       return "Linux Swap";
075     case PART_TYPE_LINUX:
076       return "Linux";
077     default:
078       return "Unknown";
079     }
080 }
081 
082 /**
083  * Detect the partitions on the given device, and registers them to
084  * the block device infrastructure.
085  */
086 sos_ret_t
087 sos_part_detect (sos_ui32_t disk_class, sos_ui32_t disk_instance,
088                  sos_size_t block_size, const char *name)
089 {
090   sos_vaddr_t buffer;
091   struct sos_blockdev_instance *blkdev;
092   struct partition_entry *part_entry;
093   unsigned int extstart = 0, extsup = 0;
094   sos_ret_t ret;
095   sos_size_t size = block_size;
096   unsigned int partnum;
097 
098   blkdev = sos_blockdev_ref_instance (disk_class, disk_instance);
099   if (blkdev == NULL)
100     return -SOS_ENOENT;
101 
102   buffer = (sos_vaddr_t) sos_kmalloc (block_size, 0);
103   if (buffer == 0)
104     {
105       sos_blockdev_release_instance (blkdev);
106       return -SOS_ENOMEM;
107     }
108 
109   ret = sos_blockdev_kernel_read (blkdev, 0, buffer, & size);
110   if (ret != SOS_OK)
111     {
112       sos_blockdev_release_instance (blkdev);
113       sos_kfree (buffer);
114       return ret;
115     }
116 
117   if (size != block_size)
118     {
119       sos_blockdev_release_instance (blkdev);
120       sos_kfree (buffer);
121       return -SOS_EIO;
122     }
123 
124   part_entry = (struct partition_entry *) (buffer + PART_TABLE_OFFSET);
125 
126   /* Handle primary partitions */
127   for (partnum = 0; partnum < 4; partnum++)
128     {
129       if (part_entry [partnum].size == 0)
130         continue;
131 
132       sos_bochs_printf ("%s%d (%lu Mb, %s) ", name, partnum+1,
133                         (part_entry[partnum].size * block_size >> 20),
134                         sos_part_type_str(part_entry[partnum].type));
135       if (part_entry [partnum].type == PART_TYPE_EXTENDED)
136         {
137           if (extstart != 0)
138             sos_bochs_printf ("Warning: two extended partitions detected\n");
139           extstart = part_entry [partnum].lba;
140           continue;
141         }
142 
143       ret = sos_blockdev_register_partition (disk_class,
144                                              disk_instance + partnum + 1,
145                                              blkdev,
146                                              part_entry[partnum].lba,
147                                              part_entry[partnum].size, NULL);
148       if (ret != SOS_OK)
149         {
150           sos_bochs_printf ("Could not register partition %d for disk %lu:%lu: error %d\n",
151                             partnum, disk_class, disk_instance, ret);
152           continue;
153         }
154     }
155 
156   while (extstart != 0 && partnum < 15)
157     {
158       ret = sos_blockdev_kernel_read (blkdev, (extstart + extsup) * block_size,
159                                       (sos_luoffset_t) buffer, & size);
160       if (ret != SOS_OK)
161         {
162           sos_blockdev_release_instance (blkdev);
163           sos_kfree (buffer);
164           return ret;
165         }
166 
167       if (size != block_size)
168         {
169           sos_blockdev_release_instance (blkdev);
170           sos_kfree (buffer);
171           return -SOS_EIO;
172         }
173 
174       sos_bochs_printf ("%s%d (%lu Mb, %s) ", name, partnum+1,
175                         (part_entry[0].size * block_size >> 20),
176                         sos_part_type_str(part_entry[0].type));
177 
178       ret = sos_blockdev_register_partition (disk_class,
179                                              disk_instance + partnum + 1,
180                                              blkdev,
181                                              extstart + part_entry[0].lba,
182                                              part_entry[0].size, NULL);
183       if (ret != SOS_OK)
184         sos_bochs_printf ("Could not register partition %d for disk %lu:%lu: error %d\n",
185                           partnum, disk_class, disk_instance, ret);
186 
187       extsup = part_entry[1].lba;
188       partnum ++;
189       if (extsup == 0)
190         break;
191     }
192 
193   sos_blockdev_release_instance (blkdev);
194   sos_kfree (buffer);
195   return SOS_OK;
196 }
197 
198 /**
199  * Remove all detected partitions on given device
200  */
201 sos_ret_t
202 sos_part_undetect (sos_ui32_t disk_class, sos_ui32_t disk_instance)
203 {
204   int partnum;
205   sos_ret_t ret;
206 
207   for (partnum = 0; partnum < 15; partnum++)
208     {
209       ret = sos_blockdev_unregister_device (disk_class, disk_instance + partnum + 1);
210       if (ret != SOS_OK)
211         sos_bochs_printf ("Warning: could not unregister partition %d of device %lu:%lu\n",
212                           partnum, disk_class, disk_instance);
213     }
214 
215   return SOS_OK;
216 }

source navigation ] diff markup ] identifier search ] general search ]