1/*
2 * Copyright (c) 2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 *  BLBootRootIdentifyDevice.c
25 *  bless
26 *
27 *  Created by Shantonu Sen on 7/16/07.
28 *  Copyright 2007 Apple Inc. All rights reserved.
29 *
30 */
31#if 0
32#include <IOKit/IOKitLib.h>
33#include <IOKit/IOKitKeys.h>
34#include <IOKit/storage/IOMedia.h>
35
36#include <CoreFoundation/CoreFoundation.h>
37
38#include <sys/param.h>
39#include <sys/stat.h>
40#include <sys/errno.h>
41
42#include "bless.h"
43#include "bless_private.h"
44
45// classify the role of a partition
46
47int _verifyIsPhysicalPartition(BLContextPtr context,
48                               io_service_t partition,
49                               io_service_t *parentWholeMedia,
50                               BLPartitionType *partType);
51
52int BLBootRootIdentifyDevice(BLContextPtr context,
53                             const char *bsdName,
54                             BLBootRootRole *role)
55{
56    int ret;
57    io_service_t service = IO_OBJECT_NULL, parentWholeMedia = IO_OBJECT_NULL;
58    BLPartitionType partType = kBLPartitionType_None;
59
60    if (bsdName == NULL || role == NULL) {
61        return EINVAL;
62    }
63
64    *role = kBLBootRootRole_Unknown;
65
66    ret = BLGetIOServiceForDeviceName(context, bsdName, &service);
67    if (ret) {
68        contextprintf(context, kBLLogLevelError, "No IOMedia for %s\n", bsdName);
69        return ENOENT;
70    }
71
72    ret = _verifyIsPhysicalPartition(context, service, &parentWholeMedia, &partType);
73    if (ret) {
74        if (service != IO_OBJECT_NULL) IOObjectRelease(service);
75        if (parentWholeMedia != IO_OBJECT_NULL) IOObjectRelease(parentWholeMedia);
76
77        contextprintf(context, kBLLogLevelError, "Can't determine topology for IOMedia %s\n", bsdName);
78        return EINVAL;
79    }
80
81    if (parentWholeMedia != IO_OBJECT_NULL) {
82        // XXX
83    }
84
85    return 0;
86}
87
88// do a topology check to make sure this partition is a leaf, its
89// grandparent is a whole partition, the GP doesn't have an IOMedia
90// ancestor
91int _verifyIsPhysicalPartition(BLContextPtr context,
92                               io_service_t partition,
93                               io_service_t *parentWholeMedia,
94                               BLPartitionType *partitionType)
95{
96    CFBooleanRef isLeaf, isWhole;
97    CFStringRef content;
98    io_service_t parent = IO_OBJECT_NULL, grandparent = IO_OBJECT_NULL;
99    kern_return_t kret;
100
101    isLeaf = IORegistryEntryCreateCFProperty(partition, CFSTR(kIOMediaLeafKey), kCFAllocatorDefault, 0);
102    if (!isLeaf || CFGetTypeID(isLeaf) != CFBooleanGetTypeID()) {
103        if (isLeaf) CFRelease(isLeaf);
104        return ENOATTR;
105    }
106
107    if (!CFEqual(isLeaf, kCFBooleanTrue)) {
108        CFRelease(isLeaf);
109        return 0; // not failure, just not a physical partition
110    }
111
112    CFRelease(isLeaf);
113
114    kret = IORegistryEntryGetParentEntry(partition, kIOServicePlane, &parent);
115    if (kret) {
116        return ENOENT;
117    }
118
119    kret = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &grandparent);
120    if (kret) {
121        IOObjectRelease(parent);
122        return ENOENT;
123    }
124
125    IOObjectRelease(parent);
126
127    if (!IOObjectConformsTo(grandparent, kIOMediaClass)) {
128        IOObjectRelease(grandparent);
129        return 0; // not a failure, just not a physical partition
130    }
131
132    isWhole = IORegistryEntryCreateCFProperty(grandparent, CFSTR(kIOMediaWholeKey), kCFAllocatorDefault, 0);
133    if (!isWhole || CFGetTypeID(isWhole) != CFBooleanGetTypeID()) {
134        if (isWhole) CFRelease(isWhole);
135        IOObjectRelease(grandparent);
136        return ENOATTR;
137    }
138
139    if (!CFEqual(isWhole, kCFBooleanTrue)) {
140        CFRelease(isWhole);
141        IOObjectRelease(grandparent);
142        return 0; // not failure, just not a physical partition
143    }
144
145    CFRelease(isWhole);
146
147    *parentWholeMedia = grandparent;
148
149    content = IORegistryEntryCreateCFProperty(grandparent,
150                                    CFSTR(kIOMediaContentKey),
151                                    kCFAllocatorDefault, 0);
152
153
154    if(!content || CFGetTypeID(content) != CFStringGetTypeID()) {
155        if (content) CFRelease(content);
156        return ENOATTR;
157    }
158
159    if(CFStringCompare(content, CFSTR("Apple_partition_scheme"), 0)
160       == kCFCompareEqualTo) {
161        if(partitionType) *partitionType = kBLPartitionType_APM;
162    } else if(CFStringCompare(content, CFSTR("FDisk_partition_scheme"), 0)
163              == kCFCompareEqualTo) {
164        if(partitionType) *partitionType = kBLPartitionType_MBR;
165    } else if(CFStringCompare(content, CFSTR("GUID_partition_scheme"), 0)
166              == kCFCompareEqualTo) {
167        if(partitionType) *partitionType = kBLPartitionType_GPT;
168    } else {
169        if(partitionType) *partitionType = kBLPartitionType_None;
170    }
171
172    return 0;
173}
174#endif
175