1/*
2 * Copyright 2013, Axel D��rfler, axeld@pinc-software.de.
3 * Copyright 2007, Ingo Weinhold, bonefish@users.sf.net.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8#include "GPTPartitionHandle.h"
9
10#include <new>
11#include <stdio.h>
12
13#include <DiskDeviceTypes.h>
14#include <MutablePartition.h>
15#include <PartitioningInfo.h>
16#include <PartitionParameterEditor.h>
17#include <Path.h>
18
19#include <AutoDeleter.h>
20
21#include "gpt_known_guids.h"
22
23
24//#define TRACE_GPT_PARTITION_HANDLE
25#undef TRACE
26#ifdef TRACE_GPT_PARTITION_HANDLE
27#	define TRACE(x...) printf(x)
28#else
29#	define TRACE(x...) do {} while (false)
30#endif
31
32
33GPTPartitionHandle::GPTPartitionHandle(BMutablePartition* partition)
34	:
35	BPartitionHandle(partition)
36{
37}
38
39
40GPTPartitionHandle::~GPTPartitionHandle()
41{
42}
43
44
45status_t
46GPTPartitionHandle::Init()
47{
48	// TODO: how to get the path of a BMutablePartition?
49	//BPath path;
50	//status_t status = Partition()->GetPath(&path);
51	//if (status != B_OK)
52		//return status;
53
54	//fd = open(path.Path(), O_RDONLY);
55	//if (fd < 0)
56		//return errno;
57
58	//fHeader = new EFI::Header(fd, Partition()->BlockSize(),
59		//Partition()->BlockSize());
60	//status = fHeader->InitCheck();
61	//if (status != B_OK)
62		//return status;
63
64	//close(fd);
65	return B_OK;
66}
67
68
69uint32
70GPTPartitionHandle::SupportedOperations(uint32 mask)
71{
72	uint32 flags = B_DISK_SYSTEM_SUPPORTS_RESIZING
73		| B_DISK_SYSTEM_SUPPORTS_MOVING
74		| B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS
75		| B_DISK_SYSTEM_SUPPORTS_INITIALIZING;
76
77	// creating child
78	if ((mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) != 0) {
79		BPartitioningInfo info;
80		if (GetPartitioningInfo(&info) == B_OK
81			&& info.CountPartitionableSpaces() > 1) {
82			flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD;
83		}
84	}
85
86	return flags;
87}
88
89
90uint32
91GPTPartitionHandle::SupportedChildOperations(const BMutablePartition* child,
92	uint32 mask)
93{
94	return B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD
95		| B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD
96		| B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE
97		| B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD;
98}
99
100
101status_t
102GPTPartitionHandle::GetNextSupportedType(const BMutablePartition* child,
103	int32* cookie, BString* type)
104{
105	int32 index = *cookie;
106	TRACE("GPTPartitionHandle::GetNextSupportedType(child: %p, cookie: %ld)\n",
107		child, index);
108
109	if (index >= int32(sizeof(kTypeMap) / sizeof(kTypeMap[0])))
110		return B_ENTRY_NOT_FOUND;
111
112	type->SetTo(kTypeMap[index].type);
113	*cookie = index + 1;
114
115	return B_OK;
116}
117
118
119status_t
120GPTPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info)
121{
122	// init to the full size (minus the GPT table header and entries)
123	off_t size = Partition()->ContentSize();
124	// TODO: use fHeader
125	size_t headerSize = Partition()->BlockSize() + 16384;
126	status_t status = info->SetTo(Partition()->BlockSize() + headerSize,
127		size - Partition()->BlockSize() - 2 * headerSize);
128	if (status != B_OK)
129		return status;
130
131	// Exclude the space of the existing partitions
132	size_t count = Partition()->CountChildren();
133	for (size_t index = 0; index < count; index++) {
134		BMutablePartition* child = Partition()->ChildAt(index);
135		status = info->ExcludeOccupiedSpace(child->Offset(), child->Size());
136		if (status != B_OK)
137			return status;
138	}
139
140	return B_OK;
141}
142
143
144status_t
145GPTPartitionHandle::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type,
146	BPartitionParameterEditor** editor)
147{
148	*editor = NULL;
149	if (type == B_CREATE_PARAMETER_EDITOR) {
150		try {
151			*editor = new BPartitionParameterEditor();
152		} catch (std::bad_alloc) {
153			return B_NO_MEMORY;
154		}
155		return B_OK;
156	}
157	return B_NOT_SUPPORTED;
158}
159
160
161status_t
162GPTPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size,
163	const char* typeString, BString* name, const char* parameters)
164{
165	return B_OK;
166}
167
168
169status_t
170GPTPartitionHandle::CreateChild(off_t offset, off_t size,
171	const char* typeString, const char* name, const char* parameters,
172	BMutablePartition** _child)
173{
174	// create the child
175	BMutablePartition* partition = Partition();
176	BMutablePartition* child;
177	status_t status = partition->CreateChild(partition->CountChildren(),
178		typeString, name, parameters, &child);
179	if (status != B_OK)
180		return status;
181
182	// init the child
183	child->SetOffset(offset);
184	child->SetSize(size);
185	child->SetBlockSize(partition->BlockSize());
186
187	*_child = child;
188	return B_OK;
189}
190
191
192status_t
193GPTPartitionHandle::DeleteChild(BMutablePartition* child)
194{
195	BMutablePartition* parent = child->Parent();
196	return parent->DeleteChild(child);
197}
198