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 *  BLSupportsLegacyMode.c
25 *  bless
26 *
27 *  Created by Shantonu Sen on 2/10/06.
28 *  Copyright 2006 Apple Computer. All Rights Reserved.
29 *
30 */
31
32#include <IOKit/IOKitLib.h>
33#include <IOKit/IOKitKeys.h>
34
35#include <sys/stat.h>
36#include "bless.h"
37#include "bless_private.h"
38
39// Check if a system supports CSM legacy mode
40
41#define kBL_APPLE_VENDOR_NVRAM_GUID "4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14"
42static bool _getFeatureFlags(BLContextPtr context, uint32_t *featureMask,
43                        uint32_t *featureFlags);
44
45bool BLSupportsLegacyMode(BLContextPtr context)
46{
47
48	uint32_t		featureMask;
49	uint32_t		featureFlags;
50
51    if(!_getFeatureFlags(context, &featureMask, &featureFlags)) {
52        return false;
53    }
54
55	if((featureMask & 0x00000001)
56	   && (featureFlags & 0x00000001)) {
57        contextprintf(context, kBLLogLevelVerbose,  "Legacy mode suppported\n");
58		return true;
59	}
60
61    contextprintf(context, kBLLogLevelVerbose,  "Legacy mode NOT suppported\n");
62    return false;
63}
64
65static bool _getFeatureFlags(BLContextPtr context, uint32_t *featureMask,
66                        uint32_t *featureFlags)
67{
68
69    io_registry_entry_t optionsNode = IO_OBJECT_NULL;
70    CFDataRef		dataRef;
71
72    optionsNode = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/options");
73
74    if(IO_OBJECT_NULL == optionsNode) {
75        contextprintf(context, kBLLogLevelVerbose,  "Could not find " kIODeviceTreePlane ":/options\n");
76        return false;
77    }
78
79    dataRef = IORegistryEntryCreateCFProperty(optionsNode,
80											 CFSTR(kBL_APPLE_VENDOR_NVRAM_GUID ":FirmwareFeaturesMask"),
81											 kCFAllocatorDefault, 0);
82
83	if(dataRef != NULL
84	   && CFGetTypeID(dataRef) == CFDataGetTypeID()
85	   && CFDataGetLength(dataRef) == sizeof(uint32_t)) {
86		const UInt8	*bytes = CFDataGetBytePtr(dataRef);
87
88		*featureMask = CFSwapInt32LittleToHost(*(uint32_t *)bytes);
89	} else {
90		*featureMask = 0x000003FF;
91	}
92
93	if(dataRef) CFRelease(dataRef);
94
95    dataRef = IORegistryEntryCreateCFProperty(optionsNode,
96											  CFSTR(kBL_APPLE_VENDOR_NVRAM_GUID ":FirmwareFeatures"),
97											  kCFAllocatorDefault, 0);
98
99	if(dataRef != NULL
100	   && CFGetTypeID(dataRef) == CFDataGetTypeID()
101	   && CFDataGetLength(dataRef) == sizeof(uint32_t)) {
102		const UInt8	*bytes = CFDataGetBytePtr(dataRef);
103
104		*featureFlags = CFSwapInt32LittleToHost(*(uint32_t *)bytes);
105	} else {
106		*featureFlags = 0x00000014;
107	}
108
109	if(dataRef) CFRelease(dataRef);
110
111	IOObjectRelease(optionsNode);
112
113	contextprintf(context, kBLLogLevelVerbose,  "Firmware feature mask: 0x%08X\n", *featureMask);
114	contextprintf(context, kBLLogLevelVerbose,  "Firmware features: 0x%08X\n", *featureFlags);
115
116    return true;
117}
118