BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / partitioning_systems / gpt / efi_gpt.cpp
blob5fc66f2b846cabc9755b6aaaef83b2bc7b7d4171
1 /*
2 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. All rights reserved.
3 * Copyright 2007-2013, Axel Dörfler, axeld@pinc-software.de.
5 * Distributed under the terms of the MIT License.
6 */
9 #include "efi_gpt.h"
11 #include <KernelExport.h>
12 #include <disk_device_manager/ddm_modules.h>
13 #include <disk_device_types.h>
14 #ifdef _BOOT_MODE
15 # include <boot/partitions.h>
16 #else
17 # include <DiskDeviceTypes.h>
18 # include "PartitionLocker.h"
19 #endif
20 #include <util/kernel_cpp.h>
22 #include <unistd.h>
23 #include <stdio.h>
24 #include <string.h>
26 #include "Header.h"
27 #include "utility.h"
30 #define TRACE_EFI_GPT
31 #ifdef TRACE_EFI_GPT
32 # define TRACE(x) dprintf x
33 #else
34 # define TRACE(x) ;
35 #endif
38 #define EFI_PARTITION_MODULE_NAME "partitioning_systems/efi_gpt/v1"
41 #ifndef _BOOT_MODE
42 static off_t
43 block_align(partition_data* partition, off_t offset, bool upwards)
45 // Take HDs into account that hide the fact they are using a
46 // block size of 4096 bytes, and round to that.
47 uint32 blockSize = max_c(partition->block_size, 4096);
48 if (upwards)
49 return ((offset + blockSize - 1) / blockSize) * blockSize;
51 return (offset / blockSize) * blockSize;
53 #endif // !_BOOT_MODE
56 // #pragma mark - public module interface
59 static status_t
60 efi_gpt_std_ops(int32 op, ...)
62 switch (op) {
63 case B_MODULE_INIT:
64 case B_MODULE_UNINIT:
65 return B_OK;
68 return B_ERROR;
72 static float
73 efi_gpt_identify_partition(int fd, partition_data* partition, void** _cookie)
75 EFI::Header* header = new (std::nothrow) EFI::Header(fd,
76 (partition->size - 1) / partition->block_size, partition->block_size);
77 status_t status = header->InitCheck();
78 if (status != B_OK) {
79 delete header;
80 return -1;
83 *_cookie = header;
84 return 0.96;
85 // This must be higher as Intel partitioning, as EFI can contain this
86 // partitioning for compatibility
90 static status_t
91 efi_gpt_scan_partition(int fd, partition_data* partition, void* _cookie)
93 TRACE(("efi_gpt_scan_partition(cookie = %p)\n", _cookie));
94 EFI::Header* header = (EFI::Header*)_cookie;
96 partition->status = B_PARTITION_VALID;
97 partition->flags |= B_PARTITION_PARTITIONING_SYSTEM;
98 partition->content_size = partition->size;
99 partition->content_cookie = header;
101 // scan all children
103 uint32 index = 0;
105 for (uint32 i = 0; i < header->EntryCount(); i++) {
106 const efi_partition_entry& entry = header->EntryAt(i);
108 if (entry.partition_type == kEmptyGUID)
109 continue;
111 if (entry.EndBlock() * partition->block_size
112 > (uint64)partition->size) {
113 TRACE(("efi_gpt: child partition exceeds existing space (ends at "
114 "block %" B_PRIu64 ")\n", entry.EndBlock()));
115 continue;
118 if (entry.StartBlock() * partition->block_size == 0) {
119 TRACE(("efi_gpt: child partition starts at 0 (recursive entry)\n"));
120 continue;
123 partition_data* child = create_child_partition(partition->id, index++,
124 partition->offset + entry.StartBlock() * partition->block_size,
125 entry.BlockCount() * partition->block_size, -1);
126 if (child == NULL) {
127 TRACE(("efi_gpt: Creating child at index %" B_PRIu32 " failed\n",
128 index - 1));
129 return B_ERROR;
132 char name[B_OS_NAME_LENGTH];
133 to_utf8(entry.name, EFI_PARTITION_NAME_LENGTH, name, sizeof(name));
134 child->name = strdup(name);
135 child->type = strdup(get_partition_type(entry.partition_type));
136 child->block_size = partition->block_size;
137 child->cookie = (void*)(addr_t)i;
140 return B_OK;
144 static void
145 efi_gpt_free_identify_partition_cookie(partition_data* partition, void* _cookie)
147 // Cookie is freed in efi_gpt_free_partition_content_cookie().
151 static void
152 efi_gpt_free_partition_content_cookie(partition_data* partition)
154 delete (EFI::Header*)partition->content_cookie;
158 #ifndef _BOOT_MODE
159 static uint32
160 efi_gpt_get_supported_operations(partition_data* partition, uint32 mask)
162 uint32 flags = B_DISK_SYSTEM_SUPPORTS_INITIALIZING
163 | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME
164 | B_DISK_SYSTEM_SUPPORTS_MOVING
165 | B_DISK_SYSTEM_SUPPORTS_RESIZING
166 | B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD;
167 // TODO: check for available entries and partitionable space and only
168 // add creating child support if both is valid
170 return flags;
174 static uint32
175 efi_gpt_get_supported_child_operations(partition_data* partition,
176 partition_data* child, uint32 mask)
178 return B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD
179 | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD
180 | B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE
181 | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD;
185 static bool
186 efi_gpt_is_sub_system_for(partition_data* partition)
188 // a GUID Partition Table doesn't usually live inside another partition
189 return false;
193 static bool
194 efi_gpt_validate_resize(partition_data* partition, off_t* size)
196 off_t newSize = *size;
197 if (newSize == partition->size)
198 return true;
200 if (newSize < 0)
201 newSize = 0;
202 else
203 newSize = block_align(partition, newSize, false);
205 // growing
206 if (newSize > partition->size) {
207 *size = newSize;
208 return true;
211 // shrinking, only so that no child would be truncated
212 off_t newEnd = partition->offset + newSize;
213 for (int32 i = 0; i < partition->child_count; i++) {
214 partition_data* child = get_child_partition(partition->id, i);
215 if (child == NULL)
216 continue;
218 if (child->offset + child->size > newEnd)
219 newEnd = child->offset + child->size;
222 newSize = block_align(partition, newEnd - partition->offset, true);
223 *size = newSize;
224 return true;
228 static bool
229 efi_gpt_validate_resize_child(partition_data* partition, partition_data* child,
230 off_t* size)
232 off_t newSize = *size;
233 if (newSize == child->size)
234 return true;
236 // shrinking
237 if (newSize < child->size) {
238 if (newSize < 0)
239 newSize = 0;
241 *size = block_align(partition, newSize, false);
242 return true;
245 // growing, but only so much that the child doesn't get bigger than
246 // the parent
247 if (child->offset + newSize > partition->offset + partition->size)
248 newSize = partition->offset + partition->size - child->offset;
250 // make sure that the child doesn't overlap any sibling partitions
251 off_t newEnd = child->offset + newSize;
252 for (int32 i = 0; i < partition->child_count; i++) {
253 partition_data* other = get_child_partition(partition->id, i);
254 if (other == NULL || other->id == child->id
255 || other->offset < child->offset)
256 continue;
258 if (newEnd > other->offset)
259 newEnd = other->offset;
262 *size = block_align(partition, newEnd - child->offset, false);
263 return true;
267 static bool
268 efi_gpt_validate_move(partition_data* partition, off_t* start)
270 // nothing to do
271 return true;
275 static bool
276 efi_gpt_validate_move_child(partition_data* partition, partition_data* child,
277 off_t* start)
279 off_t newStart = *start;
280 if (newStart < 0)
281 newStart = 0;
283 if (newStart + child->size > partition->size)
284 newStart = partition->size - child->size;
286 newStart = block_align(partition, newStart, false);
287 if (newStart > child->offset) {
288 for (int32 i = 0; i < partition->child_count; i++) {
289 partition_data* other = get_child_partition(partition->id, i);
290 if (other == NULL || other->id == child->id
291 || other->offset < child->offset)
292 continue;
294 if (other->offset < newStart + child->size)
295 newStart = other->offset - child->size;
298 newStart = block_align(partition, newStart, false);
299 } else {
300 for (int32 i = 0; i < partition->child_count; i++) {
301 partition_data* other = get_child_partition(partition->id, i);
302 if (other == NULL || other->id == child->id
303 || other->offset > child->offset)
304 continue;
306 if (other->offset + other->size > newStart)
307 newStart = other->offset + other->size;
310 newStart = block_align(partition, newStart, true);
313 *start = newStart;
314 return true;
318 static bool
319 efi_gpt_validate_set_content_name(partition_data* partition, char* name)
321 // TODO: should validate that the utf-8 -> ucs-2 is valid
322 // TODO: should count actual utf-8 chars
323 if (strlen(name) > EFI_PARTITION_NAME_LENGTH)
324 name[EFI_PARTITION_NAME_LENGTH - 1] = 0;
325 return true;
329 static bool
330 efi_gpt_validate_set_type(partition_data* partition, const char* type)
332 guid_t typeGUID;
333 return get_guid_for_partition_type(type, typeGUID);
337 static bool
338 efi_gpt_validate_initialize(partition_data* partition, char* name,
339 const char* parameters)
341 if ((efi_gpt_get_supported_operations(partition, ~0)
342 & B_DISK_SYSTEM_SUPPORTS_INITIALIZING) == 0)
343 return false;
345 // name and parameters are ignored
346 if (name != NULL)
347 name[0] = 0;
349 return true;
353 static bool
354 efi_gpt_validate_create_child(partition_data* partition, off_t* start,
355 off_t* size, const char* type, const char* name, const char* parameters,
356 int32* index)
358 if ((efi_gpt_get_supported_operations(partition, ~0)
359 & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) == 0)
360 return false;
362 if (!efi_gpt_validate_set_type(partition, type))
363 return false;
365 EFI::Header* header = (EFI::Header*)partition->content_cookie;
366 int32 entryIndex = -1;
367 for (uint32 i = 0; i < header->EntryCount(); i++) {
368 const efi_partition_entry& entry = header->EntryAt(i);
369 if (entry.partition_type == kEmptyGUID) {
370 entryIndex = i;
371 break;
375 if (entryIndex < 0)
376 return false;
378 *index = entryIndex;
380 // ensure that child lies between first and last usable block
381 off_t firstUsable = header->FirstUsableBlock() * partition->block_size;
382 if (*start < firstUsable)
383 *start = firstUsable;
385 off_t lastUsable = header->LastUsableBlock() * partition->block_size;
386 if (*start + *size > lastUsable) {
387 if (*start > lastUsable)
388 return false;
390 *size = lastUsable - *start;
393 // ensure that we don't overlap any siblings
394 for (int32 i = 0; i < partition->child_count; i++) {
395 partition_data* other = get_child_partition(partition->id, i);
396 if (other == NULL)
397 continue;
399 if (other->offset < *start && other->offset + other->size > *start)
400 *start = other->offset + other->size;
402 if (other->offset > *start && other->offset < *start + *size)
403 *size = other->offset - *start;
406 *start = block_align(partition, *start, true);
407 *size = block_align(partition, *size, false);
409 // TODO: support parameters
410 return true;
414 static status_t
415 efi_gpt_get_partitionable_spaces(partition_data* partition,
416 partitionable_space_data* buffer, int32 count, int32* actualCount)
418 // TODO: implement
419 return B_ERROR;
423 static status_t
424 efi_gpt_get_next_supported_type(partition_data* partition, int32* cookie,
425 char* type)
427 // TODO: implement
428 return B_ERROR;
432 static status_t
433 efi_gpt_shadow_changed(partition_data* partition, partition_data* child,
434 uint32 operation)
436 // TODO: implement
437 return B_ERROR;
441 static status_t
442 efi_gpt_repair(int fd, partition_id partition, bool checkOnly, disk_job_id job)
444 // TODO: implement, validate CRCs and restore from backup area if corrupt
445 return B_ERROR;
449 static status_t
450 efi_gpt_resize(int fd, partition_id partitionID, off_t size, disk_job_id job)
452 if (fd < 0)
453 return B_ERROR;
455 PartitionWriteLocker locker(partitionID);
456 if (!locker.IsLocked())
457 return B_ERROR;
459 partition_data* partition = get_partition(partitionID);
460 if (partition == NULL)
461 return B_BAD_VALUE;
463 off_t validatedSize = size;
464 if (!efi_gpt_validate_resize(partition, &validatedSize))
465 return B_BAD_VALUE;
467 update_disk_device_job_progress(job, 0.0);
469 partition->size = validatedSize;
470 partition->content_size = validatedSize;
472 update_disk_device_job_progress(job, 1.0);
473 partition_modified(partitionID);
474 return B_OK;
478 static status_t
479 efi_gpt_resize_child(int fd, partition_id partitionID, off_t size,
480 disk_job_id job)
482 if (fd < 0)
483 return B_ERROR;
485 PartitionWriteLocker locker(partitionID);
486 if (!locker.IsLocked())
487 return B_ERROR;
489 partition_data* child = get_partition(partitionID);
490 if (child == NULL)
491 return B_BAD_VALUE;
493 partition_data* partition = get_parent_partition(partitionID);
494 if (partition == NULL)
495 return B_BAD_VALUE;
497 EFI::Header* header = (EFI::Header*)partition->content_cookie;
498 if (header == NULL)
499 return B_BAD_VALUE;
501 uint32 entryIndex = (uint32)(addr_t)child->cookie;
502 if (entryIndex >= header->EntryCount())
503 return B_BAD_VALUE;
505 off_t validatedSize = size;
506 if (!efi_gpt_validate_resize_child(partition, child, &validatedSize))
507 return B_BAD_VALUE;
509 if (child->size == validatedSize)
510 return B_OK;
512 update_disk_device_job_progress(job, 0.0);
514 efi_partition_entry& entry = header->EntryAt(entryIndex);
515 entry.SetBlockCount(validatedSize / partition->block_size);
517 status_t result = header->WriteEntry(fd, entryIndex);
518 if (result != B_OK) {
519 entry.SetBlockCount(child->size / partition->block_size);
520 return result;
523 child->size = validatedSize;
525 update_disk_device_job_progress(job, 1.0);
526 partition_modified(partitionID);
527 return B_OK;
531 static status_t
532 efi_gpt_move(int fd, partition_id partition, off_t offset, disk_job_id job)
534 // nothing to do here
535 return B_OK;
539 static status_t
540 efi_gpt_move_child(int fd, partition_id partitionID, partition_id childID,
541 off_t offset, disk_job_id job)
543 if (fd < 0)
544 return B_ERROR;
546 PartitionWriteLocker locker(partitionID);
547 if (!locker.IsLocked())
548 return B_ERROR;
550 partition_data* partition = get_partition(partitionID);
551 if (partition == NULL)
552 return B_BAD_VALUE;
554 partition_data* child = get_partition(childID);
555 if (child == NULL)
556 return B_BAD_VALUE;
558 EFI::Header* header = (EFI::Header*)partition->content_cookie;
559 if (header == NULL)
560 return B_BAD_VALUE;
562 uint32 entryIndex = (uint32)(addr_t)child->cookie;
563 if (entryIndex >= header->EntryCount())
564 return B_BAD_VALUE;
566 off_t validatedOffset = offset;
567 if (!efi_gpt_validate_move_child(partition, child, &validatedOffset))
568 return B_BAD_VALUE;
570 if (child->offset == validatedOffset)
571 return B_OK;
573 // TODO: implement actual moving, need to move the partition content
574 // (the raw data) here and need to take overlap into account
575 return B_ERROR;
577 update_disk_device_job_progress(job, 0.0);
579 efi_partition_entry& entry = header->EntryAt(entryIndex);
580 uint64 blockCount = entry.BlockCount();
581 entry.SetStartBlock((validatedOffset - partition->offset)
582 / partition->block_size);
583 entry.SetBlockCount(blockCount);
585 status_t result = header->WriteEntry(fd, entryIndex);
586 if (result != B_OK) {
587 // fatal error: the data has been moved but the partition table could
588 // not be updated to reflect that change!
589 return result;
592 child->offset = validatedOffset;
594 update_disk_device_job_progress(job, 1.0);
595 partition_modified(childID);
596 return B_OK;
600 static status_t
601 efi_gpt_set_content_name(int fd, partition_id partitionID, const char* name,
602 disk_job_id job)
604 if (fd < 0)
605 return B_ERROR;
607 PartitionWriteLocker locker(partitionID);
608 if (!locker.IsLocked())
609 return B_ERROR;
611 partition_data* child = get_partition(partitionID);
612 if (child == NULL)
613 return B_BAD_VALUE;
615 partition_data* partition = get_parent_partition(partitionID);
616 if (partition == NULL)
617 return B_BAD_VALUE;
619 EFI::Header* header = (EFI::Header*)partition->content_cookie;
620 if (header == NULL)
621 return B_BAD_VALUE;
623 uint32 entryIndex = (uint32)(addr_t)child->cookie;
624 if (entryIndex >= header->EntryCount())
625 return B_BAD_VALUE;
627 update_disk_device_job_progress(job, 0.0);
629 efi_partition_entry& entry = header->EntryAt(entryIndex);
630 to_ucs2(name, strlen(name), entry.name, EFI_PARTITION_NAME_LENGTH);
632 status_t result = header->WriteEntry(fd, entryIndex);
633 if (result != B_OK)
634 return result;
636 char newName[B_OS_NAME_LENGTH];
637 to_utf8(entry.name, EFI_PARTITION_NAME_LENGTH, newName, sizeof(newName));
638 child->name = strdup(newName);
640 update_disk_device_job_progress(job, 1.0);
641 partition_modified(partitionID);
642 return B_OK;
646 static status_t
647 efi_gpt_set_type(int fd, partition_id partitionID, const char* type,
648 disk_job_id job)
650 if (fd < 0)
651 return B_ERROR;
653 PartitionWriteLocker locker(partitionID);
654 if (!locker.IsLocked())
655 return B_ERROR;
657 partition_data* child = get_partition(partitionID);
658 if (child == NULL)
659 return B_BAD_VALUE;
661 partition_data* partition = get_parent_partition(partitionID);
662 if (partition == NULL)
663 return B_BAD_VALUE;
665 EFI::Header* header = (EFI::Header*)partition->content_cookie;
666 if (header == NULL)
667 return B_BAD_VALUE;
669 uint32 entryIndex = (uint32)(addr_t)child->cookie;
670 if (entryIndex >= header->EntryCount())
671 return B_BAD_VALUE;
673 guid_t typeGUID;
674 if (!get_guid_for_partition_type(type, typeGUID))
675 return B_BAD_VALUE;
677 update_disk_device_job_progress(job, 0.0);
679 efi_partition_entry& entry = header->EntryAt(entryIndex);
680 entry.partition_type = typeGUID;
682 status_t result = header->WriteEntry(fd, entryIndex);
683 if (result != B_OK)
684 return result;
686 child->type = strdup(type);
688 update_disk_device_job_progress(job, 1.0);
689 partition_modified(partitionID);
690 return B_OK;
694 static status_t
695 efi_gpt_initialize(int fd, partition_id partitionID, const char* name,
696 const char* parameters, off_t partitionSize, disk_job_id job)
698 if (fd < 0)
699 return B_ERROR;
701 partition_data* partition = get_partition(partitionID);
702 if (partition == NULL)
703 return B_BAD_VALUE;
705 update_disk_device_job_progress(job, 0.0);
707 EFI::Header header((partitionSize - 1) / partition->block_size,
708 partition->block_size);
709 status_t result = header.InitCheck();
710 if (result != B_OK)
711 return result;
713 result = header.Write(fd);
714 if (result != B_OK)
715 return result;
717 result = scan_partition(partitionID);
718 if (result != B_OK)
719 return result;
721 update_disk_device_job_progress(job, 1.0);
722 partition_modified(partitionID);
723 return B_OK;
727 static status_t
728 efi_gpt_create_child(int fd, partition_id partitionID, off_t offset,
729 off_t size, const char* type, const char* name, const char* parameters,
730 disk_job_id job, partition_id* childID)
732 if (fd < 0)
733 return B_ERROR;
735 PartitionWriteLocker locker(partitionID);
736 if (!locker.IsLocked())
737 return B_ERROR;
739 partition_data* partition = get_partition(partitionID);
740 if (partition == NULL)
741 return B_BAD_VALUE;
743 EFI::Header* header = (EFI::Header*)partition->content_cookie;
744 if (header == NULL)
745 return B_BAD_VALUE;
747 off_t validatedOffset = offset;
748 off_t validatedSize = size;
749 uint32 entryIndex = 0;
751 if (!efi_gpt_validate_create_child(partition, &validatedOffset,
752 &validatedSize, type, name, parameters, (int32*)&entryIndex))
753 return B_BAD_VALUE;
755 guid_t typeGUID;
756 if (!get_guid_for_partition_type(type, typeGUID))
757 return B_BAD_VALUE;
759 update_disk_device_job_progress(job, 0.0);
761 partition_data* child = create_child_partition(partition->id, entryIndex,
762 validatedOffset, validatedSize, *childID);
763 if (child == NULL)
764 return B_ERROR;
766 efi_partition_entry& entry = header->EntryAt(entryIndex);
767 entry.partition_type = typeGUID;
768 // TODO: set unique partition ID
769 to_ucs2(name, strlen(name), entry.name, EFI_PARTITION_NAME_LENGTH);
770 entry.SetStartBlock((validatedOffset - partition->offset)
771 / partition->block_size);
772 entry.SetBlockCount(validatedSize / partition->block_size);
773 entry.SetAttributes(0); // TODO
775 status_t result = header->WriteEntry(fd, entryIndex);
776 if (result != B_OK) {
777 delete_partition(child->id);
778 return result;
781 *childID = child->id;
782 child->block_size = partition->block_size;
783 child->name = strdup(name);
784 child->type = strdup(type);
785 child->parameters = strdup(parameters);
786 child->cookie = (void*)(addr_t)entryIndex;
788 if (child->type == NULL || child->parameters == NULL) {
789 delete_partition(child->id);
790 return B_NO_MEMORY;
793 update_disk_device_job_progress(job, 1.0);
794 partition_modified(partitionID);
795 return B_OK;
799 static status_t
800 efi_gpt_delete_child(int fd, partition_id partitionID, partition_id childID,
801 disk_job_id job)
803 if (fd < 0)
804 return B_ERROR;
806 PartitionWriteLocker locker(partitionID);
807 if (!locker.IsLocked())
808 return B_ERROR;
810 partition_data* partition = get_partition(partitionID);
811 if (partition == NULL)
812 return B_BAD_VALUE;
814 partition_data* child = get_partition(childID);
815 if (child == NULL)
816 return B_BAD_VALUE;
818 EFI::Header* header = (EFI::Header*)partition->content_cookie;
819 if (header == NULL)
820 return B_BAD_VALUE;
822 uint32 entryIndex = (uint32)(addr_t)child->cookie;
823 if (entryIndex >= header->EntryCount())
824 return B_BAD_VALUE;
826 update_disk_device_job_progress(job, 0.0);
828 if (!delete_partition(childID))
829 return B_ERROR;
831 efi_partition_entry& entry = header->EntryAt(entryIndex);
832 entry.partition_type = kEmptyGUID;
834 status_t result = header->WriteEntry(fd, entryIndex);
835 if (result != B_OK)
836 return result;
838 update_disk_device_job_progress(job, 1.0);
839 partition_modified(partitionID);
840 return B_OK;
842 #endif // !_BOOT_MODE
845 #ifndef _BOOT_MODE
846 static partition_module_info sEFIPartitionModule = {
847 #else
848 partition_module_info gEFIPartitionModule = {
849 #endif
851 EFI_PARTITION_MODULE_NAME,
853 efi_gpt_std_ops
855 "gpt", // short_name
856 EFI_PARTITION_NAME, // pretty_name
857 0 // flags
858 | B_DISK_SYSTEM_SUPPORTS_INITIALIZING
859 | B_DISK_SYSTEM_SUPPORTS_MOVING
860 | B_DISK_SYSTEM_SUPPORTS_RESIZING
861 | B_DISK_SYSTEM_SUPPORTS_SETTING_TYPE
862 | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
863 | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME
864 | B_DISK_SYSTEM_SUPPORTS_MOVING_CHILD
865 | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD
866 | B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD
867 | B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD
870 // scanning
871 efi_gpt_identify_partition,
872 efi_gpt_scan_partition,
873 efi_gpt_free_identify_partition_cookie,
874 NULL, // free_partition_cookie
875 efi_gpt_free_partition_content_cookie,
877 #ifndef _BOOT_MODE
878 // querying
879 efi_gpt_get_supported_operations,
880 efi_gpt_get_supported_child_operations,
881 NULL, // supports_initializing_child
882 efi_gpt_is_sub_system_for,
884 efi_gpt_validate_resize,
885 efi_gpt_validate_resize_child,
886 efi_gpt_validate_move,
887 efi_gpt_validate_move_child,
888 NULL, // validate_set_name
889 efi_gpt_validate_set_content_name,
890 efi_gpt_validate_set_type,
891 NULL, // validate_set_parameters
892 NULL, // validate_set_content_parameters
893 efi_gpt_validate_initialize,
894 efi_gpt_validate_create_child,
895 efi_gpt_get_partitionable_spaces,
896 efi_gpt_get_next_supported_type,
897 NULL, // get_type_for_content_type
899 // shadow partition modification
900 efi_gpt_shadow_changed,
902 // writing
903 efi_gpt_repair,
904 efi_gpt_resize,
905 efi_gpt_resize_child,
906 efi_gpt_move,
907 efi_gpt_move_child,
908 NULL, // set_name
909 efi_gpt_set_content_name,
910 efi_gpt_set_type,
911 NULL, // set_parameters
912 NULL, // set_content_parameters
913 efi_gpt_initialize,
914 NULL, // uninitialize
915 efi_gpt_create_child,
916 efi_gpt_delete_child
917 #else
918 NULL
919 #endif // _BOOT_MODE
922 #ifndef _BOOT_MODE
923 partition_module_info* modules[] = {
924 &sEFIPartitionModule,
925 NULL
927 #endif