2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
7 #include <proto/exec.h>
8 #include <proto/partition.h>
10 #include <exec/memory.h>
11 #include <exec/types.h>
12 #include <libraries/partition.h>
14 #include "partition_support.h"
15 #include "partitionmbr.h"
28 static LONG PartitionEBRCheckPartitionTable
30 struct Library
*PartitionBase
,
31 struct PartitionHandle
*root
36 UBYTE space
[root
->de
.de_SizeBlock
<< 2];
39 struct PartitionType type
;
40 struct TagItem tags
[] = {{PT_TYPE
, (IPTR
)&type
}, {TAG_DONE
, 0}};
42 if (readBlock(PartitionBase
, root
, 0, §or
.mbr
) == 0)
44 if (AROS_LE2WORD(sector
.mbr
.magic
) == 0xAA55)
46 if (root
->root
!= NULL
)
48 GetPartitionAttrs(root
, tags
);
50 (root
->root
->table
->type
== PHPTT_MBR
) &&
51 (type
.id
[0] == MBRT_EXTENDED
52 || type
.id
[0] == MBRT_EXTENDED2
)
63 static struct PartitionHandle
*PartitionEBRNewHandle
65 struct Library
*PartitionBase
,
66 struct PartitionHandle
*root
,
73 struct PartitionHandle
*ph
;
77 ph
= AllocMem(sizeof(struct PartitionHandle
), MEMF_PUBLIC
| MEMF_CLEAR
);
82 data
= AllocMem(sizeof(struct EBRData
), MEMF_PUBLIC
);
85 cylsecs
= root
->de
.de_BlocksPerTrack
*root
->de
.de_Surfaces
;
87 data
->ebr_block_no
= ebr_block_no
;
92 /* Initialize DosEnvec */
94 /* Check if partition starts and ends on a cylinder boundary */
95 CopyMem(&root
->de
, &ph
->de
, sizeof(struct DosEnvec
));
97 block_no
% cylsecs
!= 0 ||
98 block_count
% cylsecs
!= 0
101 /* It doesn't. We could find the highest common factor of
102 first_sector and count_sector here, but currently we
103 simply use one block per cylinder */
104 ph
->de
.de_Surfaces
= 1;
105 ph
->de
.de_BlocksPerTrack
= 1;
106 cylsecs
= ph
->de
.de_BlocksPerTrack
*ph
->de
.de_Surfaces
;
108 ph
->de
.de_LowCyl
= block_no
/ cylsecs
;
109 ph
->de
.de_HighCyl
= ph
->de
.de_LowCyl
+ block_count
/cylsecs
- 1;
110 ph
->de
.de_TableSize
= 10; // only until de_HighCyl
112 /* Initialize DriveGeometry */
113 ph
->dg
.dg_DeviceType
= DG_DIRECT_ACCESS
;
114 ph
->dg
.dg_SectorSize
= ph
->de
.de_SizeBlock
<<2;
115 ph
->dg
.dg_Heads
= ph
->de
.de_Surfaces
;
116 ph
->dg
.dg_TrackSectors
= ph
->de
.de_BlocksPerTrack
;
117 ph
->dg
.dg_Cylinders
= ph
->de
.de_HighCyl
- ph
->de
.de_LowCyl
+ 1;
118 ph
->dg
.dg_BufMemType
= ph
->de
.de_BufMemType
;
121 FreeMem(ph
, sizeof(struct PartitionHandle
));
127 static LONG PartitionEBROpenPartitionTable
129 struct Library
*PartitionBase
,
130 struct PartitionHandle
*root
134 struct PartitionHandle
*ph
;
140 ebr
= AllocMem(root
->de
.de_SizeBlock
<<2, MEMF_PUBLIC
);
143 NEWLIST(&root
->table
->list
);
144 for (i
= 0; !atEnd
&& error
== 0; i
++)
146 if (readBlock(PartitionBase
, root
, block_no
, ebr
) == 0)
148 if (AROS_LE2WORD(ebr
->magic
) == 0xAA55)
150 /* Create handle for current EBR's logical partition */
152 if (AROS_LE2LONG(ebr
->pcpt
[0].count_sector
) != 0)
154 ph
= PartitionEBRNewHandle(PartitionBase
, root
,
156 block_no
+ AROS_LE2LONG(ebr
->pcpt
[0].first_sector
),
157 AROS_LE2LONG(ebr
->pcpt
[0].count_sector
),
161 Enqueue(&root
->table
->list
, &ph
->ln
);
167 /* Get location of next EBR in chain */
169 block_no
= AROS_LE2LONG(ebr
->pcpt
[1].first_sector
);
179 FreeMem(ebr
, root
->de
.de_SizeBlock
<<2);
186 static void PartitionEBRFreeHandle
188 struct Library
*PartitionBase
,
189 struct PartitionHandle
*ph
192 ClosePartitionTable(ph
);
193 FreeMem(ph
->data
, sizeof(struct EBRData
));
194 FreeMem(ph
, sizeof(struct PartitionHandle
));
197 static void PartitionEBRClosePartitionTable
199 struct Library
*PartitionBase
,
200 struct PartitionHandle
*root
203 struct PartitionHandle
*ph
;
205 while ((ph
= (struct PartitionHandle
*)RemTail(&root
->table
->list
)))
206 PartitionEBRFreeHandle(PartitionBase
, ph
);
209 static LONG PartitionEBRWritePartitionTable
211 struct Library
*PartitionBase
,
212 struct PartitionHandle
*root
215 ULONG block_no
, block_count
;
216 struct PartitionHandle
*ph
, *next_ph
, *tail
;
217 struct EBRData
*data
, *next_data
;
222 ebr
= AllocMem(root
->de
.de_SizeBlock
<< 2, MEMF_PUBLIC
| MEMF_CLEAR
);
225 ph
= (struct PartitionHandle
*)root
->table
->list
.lh_Head
;
226 tail
= (struct PartitionHandle
*)&root
->table
->list
.lh_Tail
;
230 /* Write an empty EBR block for empty partition table */
232 ebr
->magic
= AROS_WORD2LE(0xAA55);
233 if (writeBlock(PartitionBase
, root
, 0, ebr
))
239 /* First EBR must be at extended partition's first block */
240 data
= (struct EBRData
*)ph
->data
;
241 data
->ebr_block_no
= 0;
243 /* Write an EBR block for every partition in the list */
247 data
= (struct EBRData
*)ph
->data
;
248 next_ph
= (struct PartitionHandle
*)ph
->ln
.ln_Succ
;
250 /* Write table entry for current EBR's logical partition */
253 block_no
= de
->de_LowCyl
* de
->de_Surfaces
* de
->de_BlocksPerTrack
;
254 block_count
= (de
->de_HighCyl
- de
->de_LowCyl
+ 1) *
255 de
->de_Surfaces
* de
->de_BlocksPerTrack
;
257 PartitionMBRSetGeometry(root
, &ebr
->pcpt
[0], block_no
,
258 block_count
, data
->ebr_block_no
);
259 ebr
->pcpt
[0].status
= 0;
260 ebr
->pcpt
[0].type
= data
->type
;
262 /* Write table entry that points to next EBR in chain */
267 next_data
= (struct EBRData
*)next_ph
->data
;
268 block_no
= next_data
->ebr_block_no
;
269 block_count
= (de
->de_HighCyl
- de
->de_LowCyl
+ 1) *
270 de
->de_Surfaces
* de
->de_BlocksPerTrack
- block_no
;
271 ebr
->pcpt
[1].type
= MBRT_EXTENDED
;
277 ebr
->pcpt
[1].type
= 0;
279 PartitionMBRSetGeometry(root
, &ebr
->pcpt
[1], block_no
, block_count
, 0);
280 ebr
->pcpt
[1].status
= 0;
284 ebr
->magic
= AROS_WORD2LE(0xAA55);
285 if (writeBlock(PartitionBase
, root
, data
->ebr_block_no
, ebr
))
292 FreeMem(ebr
, root
->de
.de_SizeBlock
<< 2);
300 static LONG PartitionEBRCreatePartitionTable
302 struct Library
*PartitionBase
,
303 struct PartitionHandle
*ph
306 NEWLIST(&ph
->table
->list
);
310 static struct PartitionHandle
*PartitionEBRAddPartition
312 struct Library
*PartitionBase
,
313 struct PartitionHandle
*root
,
314 struct TagItem
*taglist
318 struct EBRData
*data
;
319 ULONG block_no
= 0, new_block_no
, new_block_count
, ebr_track_no
, ebr_block_no
;
320 struct PartitionHandle
*ph
, *new_ph
, *head
;
323 struct PartitionType
*ptype
;
326 tag
= findTagItem(PT_DOSENVEC
, taglist
);
332 de
= (struct DosEnvec
*)tag
->ti_Data
;
334 tag
= findTagItem(PT_TYPE
, taglist
);
341 ptype
= (struct PartitionType
*)tag
->ti_Data
;
344 de
->de_LowCyl
* de
->de_Surfaces
* de
->de_BlocksPerTrack
;
345 new_block_count
= (de
->de_HighCyl
- de
->de_LowCyl
+ 1) *
346 de
->de_Surfaces
* de
->de_BlocksPerTrack
;
348 /* Find the position in the chain/list of EBRs at which to insert
351 ph
= (struct PartitionHandle
*)root
->table
->list
.lh_TailPred
;
352 head
= (struct PartitionHandle
*)&root
->table
->list
;
354 while (ph
!= head
&& !found
)
356 data
= (struct EBRData
*)ph
->data
;
358 block_no
= de
->de_LowCyl
* de
->de_Surfaces
* de
->de_BlocksPerTrack
;
359 if (block_no
< new_block_no
)
362 ph
= (struct PartitionHandle
*)ph
->ln
.ln_Pred
;
365 /* Calculate appropriate location for new EBR */
368 ebr_track_no
= (new_block_no
- 1) / de
->de_BlocksPerTrack
;
369 ebr_block_no
= ebr_track_no
* de
->de_BlocksPerTrack
;
371 /* Create new handle and add it to list */
373 new_ph
= PartitionEBRNewHandle(PartitionBase
, root
, ptype
->id
[0],
374 new_block_no
, new_block_count
, ebr_block_no
);
375 Insert(&root
->table
->list
, &new_ph
->ln
, &ph
->ln
);
382 static void PartitionEBRDeletePartition
384 struct Library
*PartitionBase
,
385 struct PartitionHandle
*ph
389 PartitionEBRFreeHandle(PartitionBase
, ph
);
392 static LONG PartitionEBRGetPartitionTableAttrs
394 struct Library
*PartitionBase
,
395 struct PartitionHandle
*root
,
396 struct TagItem
*taglist
399 while (taglist
[0].ti_Tag
!= TAG_DONE
)
401 switch (taglist
[0].ti_Tag
)
404 *((LONG
*)taglist
[0].ti_Data
) = root
->table
->type
;
407 *((LONG
*)taglist
[0].ti_Data
) = root
->de
.de_BlocksPerTrack
;
415 static LONG PartitionEBRSetPartitionTableAttrs
417 struct Library
*PartitionBase
,
418 struct PartitionHandle
*root
,
419 struct TagItem
*taglist
422 while (taglist
[0].ti_Tag
!= TAG_DONE
)
424 switch (taglist
[0].ti_Tag
)
432 static LONG PartitionEBRGetPartitionAttrs
434 struct Library
*PartitionBase
,
435 struct PartitionHandle
*ph
,
436 struct TagItem
*taglist
440 struct PartitionHandle
*list_ph
;
442 while (taglist
[0].ti_Tag
!= TAG_DONE
)
444 struct EBRData
*data
= (struct EBRData
*)ph
->data
;
446 switch (taglist
[0].ti_Tag
)
450 struct DriveGeometry
*dg
= (struct DriveGeometry
*)taglist
[0].ti_Data
;
451 CopyMem(&ph
->dg
, dg
, sizeof(struct DriveGeometry
));
455 CopyMem(&ph
->de
, (struct DosEnvec
*)taglist
[0].ti_Data
, sizeof(struct DosEnvec
));
459 struct PartitionType
*ptype
=(struct PartitionType
*)taglist
[0].ti_Data
;
461 ptype
->id
[0] = data
->type
;
467 ForeachNode(&ph
->root
->table
->list
, list_ph
)
470 *((LONG
*)taglist
[0].ti_Data
) = i
;
480 static LONG PartitionEBRSetPartitionAttrs
482 struct Library
*PartitionBase
,
483 struct PartitionHandle
*ph
,
484 struct TagItem
*taglist
487 while (taglist
[0].ti_Tag
!= TAG_DONE
)
489 struct EBRData
*data
= (struct EBRData
*)ph
->data
;
491 switch (taglist
[0].ti_Tag
)
495 // TO DO: move handle to new position in list
497 de
= (struct DosEnvec
*)taglist
[0].ti_Data
;
498 CopyMem(de
, &ph
->de
, sizeof(struct DosEnvec
));
503 struct PartitionType
*ptype
=(struct PartitionType
*)taglist
[0].ti_Data
;
505 data
->type
= ptype
->id
[0]; // fix
514 static struct PartitionAttribute PartitionEBRPartitionTableAttrs
[]=
516 {PTTA_TYPE
, PLAM_READ
},
517 {PTTA_RESERVED
, PLAM_READ
},
518 {PTTA_MAXLEADIN
, PLAM_READ
},
522 static struct PartitionAttribute
*PartitionEBRQueryPartitionTableAttrs(
523 struct Library
*PartitionBase
)
525 return PartitionEBRPartitionTableAttrs
;
528 static struct PartitionAttribute PartitionEBRPartitionAttrs
[]=
530 {PTA_GEOMETRY
, PLAM_READ
},
531 {PTA_TYPE
, PLAM_READ
| PLAM_WRITE
},
532 {PTA_DOSENVEC
, PLAM_READ
| PLAM_WRITE
},
533 {PTA_POSITION
, PLAM_READ
},
534 {PTA_LEADIN
, PLAM_READ
},
538 static struct PartitionAttribute
*PartitionEBRQueryPartitionAttrs(
539 struct Library
*PartitionBase
)
541 return PartitionEBRPartitionAttrs
;
544 static ULONG PartitionEBRDestroyPartitionTable
546 struct Library
*PartitionBase
,
547 struct PartitionHandle
*root
550 struct PartitionHandle
*ph
;
553 while ((ph
= (struct PartitionHandle
*)RemHead(&root
->table
->list
))
556 PartitionEBRDeletePartition(PartitionBase
, ph
);
558 PartitionEBRWritePartitionTable(PartitionBase
, root
);
563 struct PTFunctionTable PartitionEBR
=
567 PartitionEBRCheckPartitionTable
,
568 PartitionEBROpenPartitionTable
,
569 PartitionEBRClosePartitionTable
,
570 PartitionEBRWritePartitionTable
,
571 PartitionEBRCreatePartitionTable
,
572 PartitionEBRAddPartition
,
573 PartitionEBRDeletePartition
,
574 PartitionEBRGetPartitionTableAttrs
,
575 PartitionEBRSetPartitionTableAttrs
,
576 PartitionEBRGetPartitionAttrs
,
577 PartitionEBRSetPartitionAttrs
,
578 PartitionEBRQueryPartitionTableAttrs
,
579 PartitionEBRQueryPartitionAttrs
,
580 PartitionEBRDestroyPartitionTable