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#include <SupportDefs.h> 19 20#include <AutoDeleter.h> 21 22#include "guid.h" 23#include "gpt_known_guids.h" 24#include "utility.h" 25 26 27//#define TRACE_GPT_PARTITION_HANDLE 28#undef TRACE 29#ifdef TRACE_GPT_PARTITION_HANDLE 30# define TRACE(x...) printf(x) 31#else 32# define TRACE(x...) do {} while (false) 33#endif 34 35 36GPTPartitionHandle::GPTPartitionHandle(BMutablePartition* partition) 37 : 38 BPartitionHandle(partition) 39{ 40} 41 42 43GPTPartitionHandle::~GPTPartitionHandle() 44{ 45} 46 47 48status_t 49GPTPartitionHandle::Init() 50{ 51 // TODO: how to get the path of a BMutablePartition? 52 //BPath path; 53 //status_t status = Partition()->GetPath(&path); 54 //if (status != B_OK) 55 //return status; 56 57 //fd = open(path.Path(), O_RDONLY); 58 //if (fd < 0) 59 //return errno; 60 61 //fHeader = new EFI::Header(fd, Partition()->BlockSize(), 62 //Partition()->BlockSize()); 63 //status = fHeader->InitCheck(); 64 //if (status != B_OK) 65 //return status; 66 67 //close(fd); 68 return B_OK; 69} 70 71 72uint32 73GPTPartitionHandle::SupportedOperations(uint32 mask) 74{ 75 uint32 flags = B_DISK_SYSTEM_SUPPORTS_RESIZING 76 | B_DISK_SYSTEM_SUPPORTS_MOVING 77 | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS 78 | B_DISK_SYSTEM_SUPPORTS_NAME 79 | B_DISK_SYSTEM_SUPPORTS_SETTING_NAME 80 | B_DISK_SYSTEM_SUPPORTS_INITIALIZING; 81 82 // creating child 83 if ((mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) != 0) { 84 BPartitioningInfo info; 85 if (GetPartitioningInfo(&info) == B_OK 86 && info.CountPartitionableSpaces() > 1) { 87 flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; 88 } 89 } 90 91 return flags; 92} 93 94 95uint32 96GPTPartitionHandle::SupportedChildOperations(const BMutablePartition* child, 97 uint32 mask) 98{ 99 return B_DISK_SYSTEM_SUPPORTS_NAME 100 | B_DISK_SYSTEM_SUPPORTS_SETTING_NAME 101 | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD 102 | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD 103 | B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE 104 | B_DISK_SYSTEM_SUPPORTS_SETTING_PARAMETERS 105 | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD; 106} 107 108 109status_t 110GPTPartitionHandle::GetNextSupportedType(const BMutablePartition* child, 111 int32* cookie, BString* type) 112{ 113 int32 index = *cookie; 114 TRACE("GPTPartitionHandle::GetNextSupportedType(child: %p, cookie: %" B_PRId32 ")\n", 115 child, index); 116 117 if (index >= int32(B_COUNT_OF(kTypeMap))) 118 return B_ENTRY_NOT_FOUND; 119 120 type->SetTo(kTypeMap[index].type); 121 *cookie = index + 1; 122 123 return B_OK; 124} 125 126 127status_t 128GPTPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info) 129{ 130 // init to the full size (minus the GPT table header and entries) 131 off_t size = Partition()->ContentSize(); 132 // TODO: use fHeader 133 size_t headerSize = Partition()->BlockSize() + 16384; 134 status_t status = info->SetTo(Partition()->BlockSize() + headerSize, 135 size - Partition()->BlockSize() - 2 * headerSize); 136 if (status != B_OK) 137 return status; 138 139 // Exclude the space of the existing partitions 140 size_t count = Partition()->CountChildren(); 141 for (size_t index = 0; index < count; index++) { 142 BMutablePartition* child = Partition()->ChildAt(index); 143 status = info->ExcludeOccupiedSpace(child->Offset(), child->Size()); 144 if (status != B_OK) 145 return status; 146 } 147 148 return B_OK; 149} 150 151 152status_t 153GPTPartitionHandle::GetParameterEditor(B_PARAMETER_EDITOR_TYPE type, 154 BPartitionParameterEditor** editor) 155{ 156 *editor = NULL; 157 if (type == B_CREATE_PARAMETER_EDITOR || type == B_PROPERTIES_PARAMETER_EDITOR) { 158 try { 159 *editor = new BPartitionParameterEditor(); 160 } catch (std::bad_alloc&) { 161 return B_NO_MEMORY; 162 } 163 return B_OK; 164 } 165 return B_NOT_SUPPORTED; 166} 167 168 169status_t 170GPTPartitionHandle::ValidateSetName(const BMutablePartition *child, BString* name) 171{ 172 // UCS-2 can use up to 2 code points per character, and GPT allows 173 // a maximum of 36 code units; 174 size_t length = name->CountChars(); 175 if (length == 0) 176 return B_OK; 177 178 size_t size = length * 2; 179 uint16 buffer[size + 1]; 180 181 do { 182 size = to_ucs2(name->String(), length, buffer, length * 2); 183 if (size <= 36) 184 return B_OK; 185 length--; 186 name->TruncateChars(length, false); 187 } while (size > 36 && length > 0); 188 189 return B_OK; 190} 191 192 193status_t 194GPTPartitionHandle::SetName(BMutablePartition* child, const char* name) 195{ 196 return child->SetName(name); 197} 198 199 200status_t 201GPTPartitionHandle::ValidateSetType(const BMutablePartition* child, 202 const char* type) 203{ 204 for (size_t i = 0; i < B_COUNT_OF(kTypeMap); i++) { 205 if (strcmp(type, kTypeMap[i].type) == 0) 206 return B_OK; 207 } 208 return B_BAD_VALUE; 209} 210 211 212status_t 213GPTPartitionHandle::SetType(BMutablePartition* child, const char* type) 214{ 215 return child->SetType(type); 216} 217 218 219status_t 220GPTPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size, 221 const char* typeString, BString* name, const char* parameters) 222{ 223 return B_OK; 224} 225 226 227status_t 228GPTPartitionHandle::CreateChild(off_t offset, off_t size, 229 const char* typeString, const char* name, const char* parameters, 230 BMutablePartition** _child) 231{ 232 // create the child 233 BMutablePartition* partition = Partition(); 234 BMutablePartition* child; 235 status_t status = partition->CreateChild(partition->CountChildren(), 236 typeString, name, parameters, &child); 237 if (status != B_OK) 238 return status; 239 240 // init the child 241 child->SetOffset(offset); 242 child->SetSize(size); 243 child->SetBlockSize(partition->BlockSize()); 244 245 *_child = child; 246 return B_OK; 247} 248 249 250status_t 251GPTPartitionHandle::DeleteChild(BMutablePartition* child) 252{ 253 BMutablePartition* parent = child->Parent(); 254 return parent->DeleteChild(child); 255} 256