The Pedigree Project 0.1
modules/drivers/common/partition/main.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pedigree/kernel/Service.h"
21#include "pedigree/kernel/ServiceFeatures.h"
22#include "pedigree/kernel/ServiceManager.h"
23#include "pedigree/kernel/machine/Device.h"
24#include "pedigree/kernel/machine/Disk.h"
25#include "pedigree/kernel/panic.h"
26#include "pedigree/kernel/process/OperationBarrier.h"
27#include "pedigree/kernel/processor/types.h"
28#include "pedigree/kernel/utilities/String.h"
29#include "pedigree/kernel/utilities/utility.h"
30
31#include "Gpt.h"
32#include "PartitionService.h"
33#include "apple.h"
34#include "modules/Module.h"
35#include "msdos.h"
36
37static Service* pService = 0;
38static ServiceFeatures* pFeatures = 0;
39static OperationBarrier g_ProbeOperations;
40
41static bool probeDevice(Disk* pDev) {
42 if (pDev->getSpecificType() == String("partition"))
43 return true;
44 for (size_t i = 0; i < pDev->getNumChildren(); ++i)
45 if (pDev->getChild(i)->getSpecificType() == String("partition"))
46 return true;
47 if (gptProbeDisk(pDev))
48 return true;
49
50 // Does the disk have an MS-DOS partition table?
51 if (msdosProbeDisk(pDev))
52 return true;
53
54 // No? how about an Apple_Map?
55 if (pDev->getNativeBlockSize() == 512 && appleProbeDisk(pDev))
56 return true;
57
58 // Oh well, better luck next time.
59 return false;
60}
61
62static Device* checkNode(Device* pDev) {
63 bool hasPartitions = false;
64 if (pDev->getType() == Device::Disk && pDev->getSpecificType() != String("partition")) {
65 // Check that none of its children are Partitions
66 // (in which case we've probed this before!)
67 for (unsigned int i = 0; i < pDev->getNumChildren(); i++) {
68 String name;
69 pDev->getChild(i)->getName(name);
70 if (pDev->getChild(i)->getSpecificType() == String("partition")) {
71 hasPartitions = true;
72 break;
73 }
74 }
75
76 if (!hasPartitions) {
77 probeDevice(static_cast<Disk*>(pDev));
78 }
79 }
80
81 return pDev;
82}
83
84bool PartitionService::serve(ServiceFeatures::Type type, void* pData, size_t dataLen) {
86 if (!g_ProbeOperations.tryAcquire(operation))
87 return false;
88
89 // Correct type?
90 if (pFeatures->provides(type)) {
91 // We only provide Touch services
92 if (type & ServiceFeatures::touch) {
93 Disk* pDisk = static_cast<Disk*>(pData);
94 if (!pDisk) {
95 return false;
96 }
97 // Boot and ATAPI discovery can already be inside Device::foreach.
98 // Runtime notifications need the same serialization for probing and
99 // publishing children, including the existing-partition check.
101 return probeDevice(pDisk);
102 }
104 return probeDevice(pDisk);
105 }
106 }
107
108 // Not provided by us, fail!
109 return false;
110}
111
112static bool entry() {
113 // Install the Partition Service
114 pService = new PartitionService;
115 pFeatures = new ServiceFeatures;
116 pFeatures->add(ServiceFeatures::touch);
117 ServiceManager::instance().addService(String("partition"), pService, pFeatures);
118
119 // Walk the device tree looking for disks that don't have "partition"
120 // children.
121 Device::foreach (checkNode);
122
123 NOTICE("partition entry() is done");
124
125 // Never fail, even if no partitions found. The partition service is still
126 // critical to the system.
127 return true;
128}
129
130static Device* removePartition(Device* device) {
131 if (device->getSpecificType() != String("partition"))
132 return device;
133
134#if !HOSTED
135 // Mounted filesystems and paging retain the physical endpoint. Closing it
136 // before deletion also excludes new users until the backing driver exits.
137 Disk* physical = static_cast<Disk*>(device)->physicalDisk();
138 if (!physical || !physical->tryCloseEndpoint())
139 panic("Partition shutdown blocked by a live disk owner");
140#endif
141
142 // Device::foreach removes the child and deletes it under the tree lock.
143 return nullptr;
144}
145
146static void exit() {
147 ServiceManager::instance().removeService(String("partition"));
148 g_ProbeOperations.closeAndWait();
149 Device::foreach (removePartition);
150 delete pService;
151 delete pFeatures;
152}
153
154#if HOSTED
155MODULE_INFO_RUNTIME_PINNED("partition", &entry, &exit, "diskimage");
156#else
157MODULE_INFO_RUNTIME_PINNED("partition", &entry, &exit);
158MODULE_OPTIONAL_DEPENDS("ata", "ahci", "nvme", "usb-mass-storage", "virtio-blk", "virtio-scsi");
159#endif
size_t getNumChildren()
Definition Device.cc:143
Device * getChild(size_t n)
Definition Device.cc:139
static void foreach(Callback callback, Device *root=0)
Definition Device.cc:107
@ Disk
A disk device - a block device in UNIX terms.
Definition Device.h:75
virtual const String & getSpecificType()
Definition Device.h:183
static bool treeLockHeldByCurrentThread()
Definition Device.cc:40
virtual void getName(String &str)
Definition Device.cc:130
virtual Type getType()
Definition Device.h:178
Definition Disk.h:35
virtual size_t getNativeBlockSize() const
Definition Disk.cc:383
MUST_USE_RESULT bool tryAcquire(Lease &lease)
bool serve(ServiceFeatures::Type type, void *pData, size_t dataLen)
virtual void add(Type s)
virtual bool provides(Type service)
void addService(const String &serviceName, Service *s, ServiceFeatures *feats)
void removeService(const String &serviceName)
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition panic.cc:118