1/*
2 * Copyright (c) 2003-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 *  BLGetRAIDBootData.c
25 *  bless
26 *
27 *  Created by Shantonu Sen on 1/13/05.
28 *  Copyright 2005-2007 Apple Inc. All Rights Reserved.
29 *
30 *
31 *  $Id: BLGetRAIDBootDataForDevice.c,v 1.8 2006/02/20 22:49:58 ssen Exp $
32 *
33 */
34
35#include <stdlib.h>
36#include <unistd.h>
37
38#include <mach/mach_error.h>
39
40#include <IOKit/IOKitLib.h>
41#include <IOKit/IOKitKeys.h>
42
43#include <CoreFoundation/CoreFoundation.h>
44
45#include "bless.h"
46#include "bless_private.h"
47
48#if SUPPORT_RAID
49
50#include <IOKit/storage/RAID/AppleRAIDUserLib.h>
51
52int BLGetRAIDBootDataForDevice(BLContextPtr context, const char * device,
53							   CFTypeRef *bootData)
54{
55	const char *name = NULL;
56	kern_return_t           kret;
57	mach_port_t             ourIOKitPort;
58	io_service_t			service;
59	io_iterator_t			serviter;
60	CFTypeRef			data = NULL;
61
62	*bootData = NULL;
63
64	if(!device || 0 != strncmp(device, "/dev/", 5)) return 1;
65
66	name = device + 5;
67
68	// Obtain the I/O Kit communication handle.
69        if((kret = IOMasterPort(bootstrap_port, &ourIOKitPort)) != KERN_SUCCESS) {
70            return 2;
71        }
72
73	kret =  IOServiceGetMatchingServices(ourIOKitPort,
74                                             IOBSDNameMatching(ourIOKitPort,
75                                                               0, name),
76                                             &serviter);
77	if (kret != KERN_SUCCESS) {
78            return 3;
79        }
80
81        service = IOIteratorNext(serviter);
82        if (!service) {
83            IOObjectRelease(serviter);
84            return 3;
85        }
86
87	IOObjectRelease(serviter);
88
89
90	// we know this IOService is a RAID member. Now we need to get the boot data
91	data = IORegistryEntrySearchCFProperty( service,
92											  kIOServicePlane,
93											  CFSTR(kIOBootDeviceKey),
94											  kCFAllocatorDefault,
95											  kIORegistryIterateRecursively|
96											  kIORegistryIterateParents);
97	if(data == NULL) {
98		// it's an error for a RAID not to have this information
99		IOObjectRelease(service);
100		return 0;
101	}
102
103	IOObjectRelease(service);
104
105	if(CFGetTypeID(data) == CFArrayGetTypeID()) {
106
107	} else if(CFGetTypeID(bootData) == CFDictionaryGetTypeID()) {
108
109	} else {
110		contextprintf(context, kBLLogLevelError,  "Invalid RAID boot data\n" );
111		return 3;
112	}
113
114	*bootData = data;
115
116	return 0;
117}
118
119#endif // SUPPORT_RAID
120