2 * Copyright (c) 2002 Marcel Moolenaar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD: src/sbin/gpt/map.c,v 1.6 2005/08/31 01:47:19 marcel Exp $
27 * $DragonFly: src/sbin/gpt/map.c,v 1.2 2007/06/17 08:34:59 dillon Exp $
30 #include <sys/types.h>
37 #define ROUNDTO 2048 // must be a power of two
38 #define ROUNDDOWN(x) ((x-1) & ~(ROUNDTO-1))
39 #define ROUNDUP(x) (ROUNDDOWN(x) + ROUNDTO)
43 static map_t
*mediamap
;
46 mkmap(off_t start
, off_t size
, int type
)
50 m
= malloc(sizeof(*m
));
55 m
->map_next
= m
->map_prev
= NULL
;
57 m
->map_index
= NOENTRY
;
63 map_add(off_t start
, off_t size
, int type
, void *data
)
68 while (n
!= NULL
&& n
->map_start
+ n
->map_size
<= start
)
73 if (n
->map_start
+ n
->map_size
< start
+ size
) {
74 warnx("error: bogus map");
78 if (n
->map_start
== start
&& n
->map_size
== size
) {
79 if (n
->map_type
!= MAP_TYPE_UNUSED
) {
80 if (n
->map_type
!= MAP_TYPE_MBR_PART
||
81 type
!= MAP_TYPE_GPT_PART
) {
82 warnx("warning: partition(%llu,%llu) mirrored",
83 (long long)start
, (long long)size
);
91 if (n
->map_type
!= MAP_TYPE_UNUSED
) {
92 if (n
->map_type
!= MAP_TYPE_MBR_PART
||
93 type
!= MAP_TYPE_GPT_PART
) {
94 warnx("error: bogus map");
97 n
->map_type
= MAP_TYPE_UNUSED
;
100 m
= mkmap(start
, size
, type
);
106 if (start
== n
->map_start
) {
107 m
->map_prev
= n
->map_prev
;
109 if (m
->map_prev
!= NULL
)
110 m
->map_prev
->map_next
= m
;
114 n
->map_start
+= size
;
116 } else if (start
+ size
== n
->map_start
+ n
->map_size
) {
118 m
->map_next
= p
->map_next
;
120 if (m
->map_next
!= NULL
)
121 m
->map_next
->map_prev
= m
;
125 p
= mkmap(n
->map_start
, start
- n
->map_start
, n
->map_type
);
126 n
->map_start
+= p
->map_size
+ m
->map_size
;
127 n
->map_size
-= (p
->map_size
+ m
->map_size
);
128 p
->map_prev
= n
->map_prev
;
133 if (p
->map_prev
!= NULL
)
134 p
->map_prev
->map_next
= p
;
143 map_alloc(off_t start
, off_t size
)
148 if (start
== 0 && size
!= 0)
149 size
= ROUNDUP(size
);
150 for (m
= mediamap
; m
!= NULL
; m
= m
->map_next
) {
151 if (m
->map_type
!= MAP_TYPE_UNUSED
|| m
->map_start
< 2)
153 if (start
!= 0 && m
->map_start
> start
)
155 delta
= (start
!= 0) ? start
- m
->map_start
: ROUNDUP(m
->map_start
) - m
->map_start
;
156 if (size
== 0 || m
->map_size
- delta
>= size
) {
157 if (m
->map_size
- delta
<= 0)
160 size
= m
->map_size
- delta
;
162 size
= ROUNDDOWN(size
);
164 return (map_add(m
->map_start
+ delta
, size
,
165 MAP_TYPE_GPT_PART
, NULL
));
178 while (m
!= NULL
&& m
->map_type
!= type
)
195 while (m
!= NULL
&& m
->map_next
!= NULL
)
201 map_free(off_t start
, off_t size
)
207 while (m
!= NULL
&& m
->map_start
+ m
->map_size
<= start
)
209 if (m
== NULL
|| m
->map_type
!= MAP_TYPE_UNUSED
)
212 return ((m
->map_start
+ m
->map_size
>= start
+ size
) ? 1 : 0);
213 return (m
->map_size
- (start
- m
->map_start
));
221 mediamap
= mkmap(0LL, size
, MAP_TYPE_UNUSED
);
222 lbawidth
= sprintf(buf
, "%llu", (long long)size
);