1/*
2 * Copyright (c) 2006-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 *  BLGetOpenFirmwareBootDeviceForNetworkPath.c
25 *  bless
26 *
27 *  Created by Shantonu Sen on 4/11/06.
28 *  Copyright 2006-2007 Apple Inc. All Rights Reserved.
29 *
30 * $Id: BLGetOpenFirmwareBootDeviceForNetworkPath.c,v 1.1 2006/04/12 00:15:05 ssen Exp $
31 *
32 */
33
34#import <IOKit/IOKitLib.h>
35#import <IOKit/IOBSD.h>
36#import <IOKit/IOKitKeys.h>
37#include <IOKit/network/IONetworkInterface.h>
38#include <IOKit/network/IONetworkController.h>
39
40#import <CoreFoundation/CoreFoundation.h>
41
42#include <stdlib.h>
43#include <stdio.h>
44#include <unistd.h>
45#include <sys/stat.h>
46#include <sys/param.h>
47
48#include "bless.h"
49#include "bless_private.h"
50
51int BLGetOpenFirmwareBootDeviceForNetworkPath(BLContextPtr context,
52                                               const char *interface,
53                                               const char *host,
54                                               const char *path,
55											   char * ofstring) {
56
57    mach_port_t masterPort;
58    kern_return_t kret;
59    io_service_t iface, service;
60	io_iterator_t iter;
61	io_string_t	pathInPlane;
62	bool gotPathInPlane = false;
63
64    CFMutableDictionaryRef matchDict;
65
66    kret = IOMasterPort(MACH_PORT_NULL, &masterPort);
67    if(kret) return 1;
68
69
70    matchDict = IOBSDNameMatching(masterPort, 0, interface);
71    CFDictionarySetValue(matchDict, CFSTR(kIOProviderClassKey), CFSTR(kIONetworkInterfaceClass));
72
73
74    iface = IOServiceGetMatchingService(masterPort,
75                                        matchDict);
76
77    if(iface == IO_OBJECT_NULL) {
78        contextprintf(context, kBLLogLevelError, "Could not find object for %s\n", interface);
79        return 1;
80    }
81
82	// find this the parent that's in the device tree plane
83	kret = IORegistryEntryCreateIterator(iface, kIOServicePlane,
84		kIORegistryIterateRecursively|kIORegistryIterateParents,
85		&iter);
86	IOObjectRelease(iface);
87
88	if(kret) {
89        contextprintf(context, kBLLogLevelError, "Could not find object for %s\n", interface);
90        return 2;
91	}
92
93	while ( (service = IOIteratorNext(iter)) != IO_OBJECT_NULL ) {
94
95		kret = IORegistryEntryGetPath(service, kIODeviceTreePlane, pathInPlane);
96		if(kret == 0) {
97			gotPathInPlane = true;
98			IOObjectRelease(service);
99			break;
100		}
101
102		IOObjectRelease(service);
103	}
104	IOObjectRelease(iter);
105
106	if(!gotPathInPlane) {
107        contextprintf(context, kBLLogLevelError, "Could not find parent for %s in device tree\n", interface);
108		return 3;
109	}
110
111	contextprintf(context, kBLLogLevelVerbose, "Got path %s for interface %s\n", pathInPlane, interface);
112
113	if(host && path && strlen(path)) {
114		sprintf(ofstring, "%s:%s,%s", pathInPlane + strlen(kIODeviceTreePlane) + 1, host, path);
115	} else {
116		sprintf(ofstring, "%s:bootp", pathInPlane + strlen(kIODeviceTreePlane) + 1);
117	}
118
119	return 0;
120}
121