2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
7 #include <exec/memory.h>
8 #include <exec/types.h>
9 #include <libraries/partition.h>
10 #include <proto/exec.h>
11 #include <proto/partition.h>
12 #include <proto/utility.h>
14 #include "partition_types.h"
15 #include "partition_support.h"
16 #include "partitionmbr.h"
23 ULONG ebr_block_no
; /* Home block of the record itself */
24 ULONG block_no
; /* Start partition block */
25 ULONG block_count
; /* Length of partition in blocks */
28 static LONG PartitionEBRCheckPartitionTable
30 struct Library
*PartitionBase
,
31 struct PartitionHandle
*root
39 struct PartitionType type
;
40 struct TagItem tags
[] = {{PT_TYPE
, (IPTR
)&type
}, {TAG_DONE
, 0}};
42 if ((root
->de
.de_SizeBlock
<< 2) > sizeof(sector
))
45 if (readBlock(PartitionBase
, root
, 0, §or
.mbr
) == 0)
47 if (AROS_LE2WORD(sector
.mbr
.magic
) == 0xAA55)
49 if (root
->root
!= NULL
)
51 GetPartitionAttrs(root
, tags
);
53 (root
->root
->table
->type
== PHPTT_MBR
) &&
54 (type
.id
[0] == MBRT_EXTENDED
55 || type
.id
[0] == MBRT_EXTENDED2
)
66 static struct PartitionHandle
*PartitionEBRNewHandle(struct Library
*PartitionBase
, struct PartitionHandle
*root
,
67 UBYTE type
, ULONG block_no
, ULONG block_count
, ULONG ebr_block_no
)
69 struct PartitionHandle
*ph
;
71 ph
= AllocMem(sizeof(struct PartitionHandle
), MEMF_PUBLIC
| MEMF_CLEAR
);
76 data
= AllocMem(sizeof(struct EBRData
), MEMF_PUBLIC
);
80 data
->ebr_block_no
= ebr_block_no
;
81 data
->block_no
= block_no
;
82 data
->block_count
= block_count
;
86 /* Initialize DosEnvec and DriveGeometry */
87 initPartitionHandle(root
, ph
, block_no
, block_count
);
89 /* Map type ID to a DOSType */
90 setDosType(&ph
->de
, MBR_FindDosType(data
->type
));
94 FreeMem(ph
, sizeof(struct PartitionHandle
));
99 static LONG PartitionEBROpenPartitionTable
101 struct Library
*PartitionBase
,
102 struct PartitionHandle
*root
106 struct PartitionHandle
*ph
;
112 ebr
= AllocMem(root
->de
.de_SizeBlock
<<2, MEMF_PUBLIC
);
115 NEWLIST(&root
->table
->list
);
116 for (i
= 0; !atEnd
&& error
== 0; i
++)
118 if (readBlock(PartitionBase
, root
, block_no
, ebr
) == 0)
120 if (AROS_LE2WORD(ebr
->magic
) == 0xAA55)
122 /* Create handle for current EBR's logical partition */
124 if (AROS_LE2LONG(ebr
->pcpt
[0].count_sector
) != 0)
126 ph
= PartitionEBRNewHandle(PartitionBase
, root
,
128 block_no
+ AROS_LE2LONG(ebr
->pcpt
[0].first_sector
),
129 AROS_LE2LONG(ebr
->pcpt
[0].count_sector
),
133 Enqueue(&root
->table
->list
, &ph
->ln
);
139 /* Get location of next EBR in chain */
141 block_no
= AROS_LE2LONG(ebr
->pcpt
[1].first_sector
);
151 FreeMem(ebr
, root
->de
.de_SizeBlock
<<2);
158 static void PartitionEBRFreeHandle
160 struct Library
*PartitionBase
,
161 struct PartitionHandle
*ph
164 ClosePartitionTable(ph
);
165 FreeMem(ph
->data
, sizeof(struct EBRData
));
166 FreeMem(ph
, sizeof(struct PartitionHandle
));
169 static void PartitionEBRClosePartitionTable
171 struct Library
*PartitionBase
,
172 struct PartitionHandle
*root
175 struct PartitionHandle
*ph
;
177 while ((ph
= (struct PartitionHandle
*)RemTail(&root
->table
->list
)))
178 PartitionEBRFreeHandle(PartitionBase
, ph
);
181 static LONG PartitionEBRWritePartitionTable
183 struct Library
*PartitionBase
,
184 struct PartitionHandle
*root
187 ULONG block_no
, block_count
;
188 struct PartitionHandle
*ph
, *next_ph
, *tail
;
189 struct EBRData
*data
, *next_data
;
194 ebr
= AllocMem(root
->de
.de_SizeBlock
<< 2, MEMF_PUBLIC
| MEMF_CLEAR
);
197 ph
= (struct PartitionHandle
*)root
->table
->list
.lh_Head
;
198 tail
= (struct PartitionHandle
*)&root
->table
->list
.lh_Tail
;
202 /* Write an empty EBR block for empty partition table */
204 ebr
->magic
= AROS_WORD2LE(0xAA55);
205 if (writeBlock(PartitionBase
, root
, 0, ebr
))
211 /* First EBR must be at extended partition's first block */
212 data
= (struct EBRData
*)ph
->data
;
213 data
->ebr_block_no
= 0;
215 /* Write an EBR block for every partition in the list */
219 data
= (struct EBRData
*)ph
->data
;
220 next_ph
= (struct PartitionHandle
*)ph
->ln
.ln_Succ
;
222 /* Write table entry for current EBR's logical partition */
225 block_no
= de
->de_LowCyl
* de
->de_Surfaces
* de
->de_BlocksPerTrack
;
226 block_count
= (de
->de_HighCyl
- de
->de_LowCyl
+ 1) *
227 de
->de_Surfaces
* de
->de_BlocksPerTrack
;
229 PartitionMBRSetGeometry(root
, &ebr
->pcpt
[0], block_no
,
230 block_count
, data
->ebr_block_no
);
231 ebr
->pcpt
[0].status
= 0;
232 ebr
->pcpt
[0].type
= data
->type
;
234 /* Write table entry that points to next EBR in chain */
239 next_data
= (struct EBRData
*)next_ph
->data
;
240 block_no
= next_data
->ebr_block_no
;
241 block_count
= (de
->de_HighCyl
- de
->de_LowCyl
+ 1) *
242 de
->de_Surfaces
* de
->de_BlocksPerTrack
- block_no
;
243 ebr
->pcpt
[1].type
= MBRT_EXTENDED
;
249 ebr
->pcpt
[1].type
= 0;
251 PartitionMBRSetGeometry(root
, &ebr
->pcpt
[1], block_no
, block_count
, 0);
252 ebr
->pcpt
[1].status
= 0;
256 ebr
->magic
= AROS_WORD2LE(0xAA55);
257 if (writeBlock(PartitionBase
, root
, data
->ebr_block_no
, ebr
))
264 FreeMem(ebr
, root
->de
.de_SizeBlock
<< 2);
272 static LONG PartitionEBRCreatePartitionTable
274 struct Library
*PartitionBase
,
275 struct PartitionHandle
*ph
278 NEWLIST(&ph
->table
->list
);
282 static struct PartitionHandle
*PartitionEBRAddPartition(struct Library
*PartitionBase
, struct PartitionHandle
*root
, const struct TagItem
*taglist
)
285 ULONG block_no
= 0, new_block_no
, new_block_count
, ebr_track_no
, ebr_block_no
;
286 struct PartitionHandle
*ph
, *new_ph
, *head
;
289 struct PartitionType
*ptype
;
292 tag
= FindTagItem(PT_DOSENVEC
, taglist
);
298 de
= (struct DosEnvec
*)tag
->ti_Data
;
300 tag
= FindTagItem(PT_TYPE
, taglist
);
307 ptype
= (struct PartitionType
*)tag
->ti_Data
;
310 de
->de_LowCyl
* de
->de_Surfaces
* de
->de_BlocksPerTrack
;
311 new_block_count
= (de
->de_HighCyl
- de
->de_LowCyl
+ 1) *
312 de
->de_Surfaces
* de
->de_BlocksPerTrack
;
314 /* Find the position in the chain/list of EBRs at which to insert
317 ph
= (struct PartitionHandle
*)root
->table
->list
.lh_TailPred
;
318 head
= (struct PartitionHandle
*)&root
->table
->list
;
320 while (ph
!= head
&& !found
)
323 block_no
= de
->de_LowCyl
* de
->de_Surfaces
* de
->de_BlocksPerTrack
;
324 if (block_no
< new_block_no
)
327 ph
= (struct PartitionHandle
*)ph
->ln
.ln_Pred
;
330 /* Calculate appropriate location for new EBR */
333 ebr_track_no
= (new_block_no
- 1) / de
->de_BlocksPerTrack
;
334 ebr_block_no
= ebr_track_no
* de
->de_BlocksPerTrack
;
336 /* Create new handle and add it to list */
338 new_ph
= PartitionEBRNewHandle(PartitionBase
, root
, ptype
->id
[0],
339 new_block_no
, new_block_count
, ebr_block_no
);
340 Insert(&root
->table
->list
, &new_ph
->ln
, &ph
->ln
);
347 static void PartitionEBRDeletePartition
349 struct Library
*PartitionBase
,
350 struct PartitionHandle
*ph
354 PartitionEBRFreeHandle(PartitionBase
, ph
);
357 static LONG
PartitionEBRGetPartitionTableAttr(struct Library
*PartitionBase
,
358 struct PartitionHandle
*root
, const struct TagItem
*tag
)
363 *((LONG
*)tag
->ti_Data
) = root
->de
.de_BlocksPerTrack
;
370 static LONG
PartitionEBRGetPartitionAttr(struct Library
*PartitionBase
,
371 struct PartitionHandle
*ph
, const struct TagItem
*tag
)
373 struct EBRData
*data
= (struct EBRData
*)ph
->data
;
378 PTYPE(tag
->ti_Data
)->id
[0] = data
->type
;
379 PTYPE(tag
->ti_Data
)->id_len
= 1;
383 *((UQUAD
*)tag
->ti_Data
) = data
->block_no
;
387 *((UQUAD
*)tag
->ti_Data
) = data
->block_no
+ data
->block_count
- 1;
394 static LONG
PartitionEBRSetPartitionAttrs(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, const struct TagItem
*taglist
)
396 struct EBRData
*data
= (struct EBRData
*)ph
->data
;
399 while ((tag
= NextTagItem((struct TagItem
**)&taglist
)))
404 // TO DO: move handle to new position in list
405 CopyMem((struct DosEnvec
*)tag
->ti_Data
, &ph
->de
, sizeof(struct DosEnvec
));
408 data
->type
= PTYPE(tag
->ti_Data
)->id
[0]; // fix
409 /* Update DOSType according to a new type ID */
410 setDosType(&ph
->de
, MBR_FindDosType(data
->type
));
418 static const struct PartitionAttribute PartitionEBRPartitionTableAttrs
[]=
420 {PTT_TYPE
, PLAM_READ
},
421 {PTT_RESERVED
, PLAM_READ
},
422 {PTT_MAXLEADIN
, PLAM_READ
},
426 static const struct PartitionAttribute PartitionEBRPartitionAttrs
[]=
428 {PT_GEOMETRY
, PLAM_READ
},
429 {PT_TYPE
, PLAM_READ
| PLAM_WRITE
},
430 {PT_DOSENVEC
, PLAM_READ
| PLAM_WRITE
},
431 {PT_POSITION
, PLAM_READ
},
432 {PT_LEADIN
, PLAM_READ
},
433 {PT_STARTBLOCK
, PLAM_READ
},
434 {PT_ENDBLOCK
, PLAM_READ
},
438 static ULONG PartitionEBRDestroyPartitionTable
440 struct Library
*PartitionBase
,
441 struct PartitionHandle
*root
444 struct PartitionHandle
*ph
;
447 while ((ph
= (struct PartitionHandle
*)RemHead(&root
->table
->list
))
450 PartitionEBRDeletePartition(PartitionBase
, ph
);
452 PartitionEBRWritePartitionTable(PartitionBase
, root
);
457 const struct PTFunctionTable PartitionEBR
=
461 PartitionEBRCheckPartitionTable
,
462 PartitionEBROpenPartitionTable
,
463 PartitionEBRClosePartitionTable
,
464 PartitionEBRWritePartitionTable
,
465 PartitionEBRCreatePartitionTable
,
466 PartitionEBRAddPartition
,
467 PartitionEBRDeletePartition
,
468 PartitionEBRGetPartitionTableAttr
,
470 PartitionEBRGetPartitionAttr
,
471 PartitionEBRSetPartitionAttrs
,
472 PartitionEBRPartitionTableAttrs
,
473 PartitionEBRPartitionAttrs
,
474 PartitionEBRDestroyPartitionTable
,