1/*
2 * Copyright (c) 2005-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 *  BLCreateEFIXMLRepresentationForNetworkPath.c
25 *  bless
26 *
27 *  Created by Shantonu Sen on 11/15/05.
28 *  Copyright 2005-2007 Apple Inc. All Rights Reserved.
29 *
30 */
31
32#import <IOKit/IOKitLib.h>
33#import <IOKit/IOCFSerialize.h>
34#import <IOKit/IOBSD.h>
35#import <IOKit/IOKitKeys.h>
36#include <IOKit/network/IONetworkInterface.h>
37#include <IOKit/network/IONetworkController.h>
38
39#import <CoreFoundation/CoreFoundation.h>
40
41#include <string.h>
42#include <sys/param.h>
43#include <sys/stat.h>
44
45#include "bless.h"
46#include "bless_private.h"
47
48int BLCreateEFIXMLRepresentationForNetworkPath(BLContextPtr context,
49                                               BLNetBootProtocolType protocol,
50                                               const char *interface,
51                                               const char *host,
52                                               const char *path,
53                                               const char *optionalData,
54                                               CFStringRef *xmlString)
55{
56    mach_port_t masterPort;
57    kern_return_t kret;
58    io_service_t iface;
59
60    CFDataRef xmlData;
61    CFMutableDictionaryRef dict, matchDict;
62    CFMutableArrayRef array;
63    CFDataRef macAddress;
64
65    const UInt8 *xmlBuffer;
66    UInt8 *outBuffer;
67    CFIndex count;
68
69    kret = IOMasterPort(MACH_PORT_NULL, &masterPort);
70    if(kret) return 1;
71
72
73
74    array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
75
76    dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
77                                     &kCFTypeDictionaryValueCallBacks);
78
79    matchDict = IOBSDNameMatching(masterPort, 0, interface);
80    CFDictionarySetValue(matchDict, CFSTR(kIOProviderClassKey), CFSTR(kIONetworkInterfaceClass));
81
82    CFRetain(matchDict);
83    iface = IOServiceGetMatchingService(masterPort,
84                                        matchDict);
85
86    if(iface == IO_OBJECT_NULL) {
87        contextprintf(context, kBLLogLevelError, "Could not find object for %s\n", interface);
88        CFRelease(matchDict);
89        CFRelease(dict);
90        CFRelease(array);
91        return 1;
92    }
93
94    CFDictionaryAddValue(dict, CFSTR("IOMatch"), matchDict);
95    CFRelease(matchDict);
96
97    macAddress = IORegistryEntrySearchCFProperty(iface, kIOServicePlane,
98                                                 CFSTR(kIOMACAddress),
99                                                 kCFAllocatorDefault,
100                                                 kIORegistryIterateRecursively|kIORegistryIterateParents);
101    if(macAddress) {
102        contextprintf(context, kBLLogLevelVerbose, "MAC address %s found for %s\n",
103					  BLGetCStringDescription(macAddress), interface);
104
105        CFDictionaryAddValue(dict, CFSTR("BLMACAddress"), macAddress);
106        CFRelease(macAddress);
107    } else {
108        contextprintf(context, kBLLogLevelVerbose, "No MAC address found for %s\n", interface);
109    }
110
111    IOObjectRelease(iface);
112
113    CFArrayAppendValue(array, dict);
114    CFRelease(dict);
115
116    if(host) {
117        CFStringRef hostString;
118
119        hostString = CFStringCreateWithCString(kCFAllocatorDefault, host, kCFStringEncodingUTF8);
120
121        dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
122                                         &kCFTypeDictionaryValueCallBacks);
123        CFDictionaryAddValue(dict, CFSTR("IOEFIDevicePathType"),
124                             CFSTR("MessagingIPv4"));
125        CFDictionaryAddValue(dict, CFSTR("RemoteIpAddress"),
126                             hostString);
127        CFArrayAppendValue(array, dict);
128        CFRelease(dict);
129        CFRelease(hostString);
130
131        if(path) {
132            CFStringRef pathString;
133
134            pathString = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8);
135
136            dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
137                                             &kCFTypeDictionaryValueCallBacks);
138            CFDictionaryAddValue(dict, CFSTR("IOEFIDevicePathType"),
139                                 CFSTR("MediaFilePath"));
140            CFDictionaryAddValue(dict, CFSTR("Path"),
141                                 pathString);
142            CFArrayAppendValue(array, dict);
143            CFRelease(dict);
144            CFRelease(pathString);
145        }
146
147    }
148
149    contextprintf(context, kBLLogLevelVerbose, "Netboot protocol %d\n", protocol);
150    if (protocol == kBLNetBootProtocol_PXE) {
151        dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
152                                         &kCFTypeDictionaryValueCallBacks);
153        CFDictionaryAddValue(dict, CFSTR("IOEFIDevicePathType"),
154                             CFSTR("MessagingNetbootProtocol"));
155        CFDictionaryAddValue(dict, CFSTR("Protocol"),
156                             CFSTR("FE3913DB-9AEE-4E40-A294-ABBE93A1A4B7"));
157        CFArrayAppendValue(array, dict);
158        CFRelease(dict);
159    }
160
161    if(optionalData) {
162        CFStringRef optString = CFStringCreateWithCString(kCFAllocatorDefault, optionalData, kCFStringEncodingUTF8);
163
164        dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
165                                         &kCFTypeDictionaryValueCallBacks);
166        CFDictionaryAddValue(dict, CFSTR("IOEFIBootOption"),
167                             optString);
168        CFArrayAppendValue(array, dict);
169        CFRelease(dict);
170
171        CFRelease(optString);
172    }
173
174    xmlData = IOCFSerialize(array, 0);
175    CFRelease(array);
176
177    if(xmlData == NULL) {
178        contextprintf(context, kBLLogLevelError, "Can't create XML representation\n");
179        return 2;
180    }
181
182    count = CFDataGetLength(xmlData);
183    xmlBuffer = CFDataGetBytePtr(xmlData);
184    outBuffer = calloc(count+1, sizeof(char)); // terminate
185
186    memcpy(outBuffer, xmlBuffer, count);
187    CFRelease(xmlData);
188
189    *xmlString = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)outBuffer, kCFStringEncodingUTF8);
190
191    free(outBuffer);
192
193    return 0;
194}
195
196