1/*
2 * Copyright (c) 2006-2012 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 * FILE: bootcaches.h
25 * AUTH: Soren Spies (sspies)
26 * DATE: "spring" 2006
27 * DESC: routines for dealing with bootcaches.plist data, bootstamps, etc
28 *       shared between kextcache and kextd
29 *
30 */
31
32#ifndef __BOOTCACHES_H__
33#define __BOOTCACHES_H__
34
35#include <CoreFoundation/CoreFoundation.h>
36#include <DiskArbitration/DiskArbitration.h>
37#include <sys/stat.h>
38#include <sys/time.h>
39#include <IOKit/kext/kextmanager_types.h>   // uuid_string_t
40#include <mach-o/arch.h>
41
42#include "bootroot_internal.h"      // includes bootroot.h
43
44// cache directories that we create (we also create kCSFDEPropertyCacheDir)
45#define kTSCacheDir         "/System/Library/Caches/com.apple.bootstamps"
46#define kCacheDirMode       0755        // Sec reviewed
47#define kCacheFileMode      0644
48
49// bootcaches.plist and keys
50
51#define kBootCachesPath             "/usr/standalone/bootcaches.plist"
52#define kBCPreBootKey               CFSTR("PreBootPaths")    // dict
53#define kBCLabelKey                 CFSTR("DiskLabel")       // ".disk_label"
54#define kBCBootersKey               CFSTR("BooterPaths")     // dict
55#define kBCEFIBooterKey             CFSTR("EFIBooter")       // "boot.efi"
56#define kBCOFBooterKey              CFSTR("OFBooter")        // "BootX"
57#define kBCPostBootKey              CFSTR("PostBootPaths")   // dict
58#define kBCMKextKey                 CFSTR("MKext")           // dict
59#define kBCMKext2Key                CFSTR("MKext2")          // dict
60#define kBCKernelcacheV1Key         CFSTR("Kernelcache v1.1")// dict
61#define kBCKernelcacheV2Key         CFSTR("Kernelcache v1.2")// dict
62#define kBCKernelcacheV3Key         CFSTR("Kernelcache v1.3")// dict
63#define kBCKernelPathKey            CFSTR("KernelPath")      //   m_k | kernel
64#define kBCPreferredCompressionKey  CFSTR("Preferred Compression") // "lzvn"
65#if DEV_KERNEL_SUPPORT
66#define kBCKernelsDirKey            CFSTR("KernelsDir")      //   S/L/Kernels
67#endif
68#define kBCArchsKey                 CFSTR("Archs")           //   ... i386
69#define kBCExtensionsDirKey         CFSTR("ExtensionsDir")   //   /S/L/E, /L/E
70#define kBCPathKey                  CFSTR("Path")            //   ...kernelcache
71// AdditionalPaths are optional w/PreBootPaths, required w/PostBootPaths
72#define kBCAdditionalPathsKey       CFSTR("AdditionalPaths") // array
73#define kBCBootConfigKey            CFSTR("BootConfig")      // bc.plist
74#define kBCEncryptedRootKey         CFSTR("EncryptedRoot")   // dict
75#define kBCCSFDEPropertyCacheKey    CFSTR("EncryptedPropertyCache") // .wipekey
76#define kBCCSFDERootVolPropCacheKey CFSTR("RootVolumePropertyCache")//A_B only?
77#define kBCCSFDEDefResourcesDirKey  CFSTR("DefaultResourcesDir") // EfiLoginUI
78#define kBCCSFDELocalizationSrcKey  CFSTR("LocalizationSource")  // EFI.fr/Res
79#define kBCCSFDELanguagesPrefKey    CFSTR("LanguagesPref")   //   .GlobalPrefs
80#define kBCCSFDEBackgroundImageKey  CFSTR("BackgroundImage") //   desktop..png
81#define kBCCSFDELocRsrcsCacheKey    CFSTR("LocalizedResourcesCache") // EFILocs
82
83
84typedef enum {
85    kMkextCRCError = -1,
86    kMkextCRCFound = 0,
87    kMkextCRCNotFound = 1,
88} MkextCRCResult;
89
90// 6486172 points out that kextd ends up with a lot of these buffers
91// (especially w/multiple OS vols).  BCPATH_MAX (8163405) reduces the impact.
92#define NCHARSUUID      (2*sizeof(uuid_t) + 5)  // hex with 4 -'s and one NUL
93#define BCPATH_MAX      128
94#define TSPATH_MAX      (BCPATH_MAX + 1 + NCHARSUUID + 1 + BCPATH_MAX)
95#define DEVMAXPATHSIZE  128                     // xnu/devfs/devfsdefs.h:
96#define ROOTPATH_MAX    (sizeof("/Volumes/") + NAME_MAX)
97
98typedef struct {
99    char rpath[BCPATH_MAX];     // (relative) source path in root filesystem
100    char tspath[TSPATH_MAX];    // shadow timestamp path tracking Apple_Boot[s]
101    struct timeval tstamps[2];  // rpath's initial timestamp(s)
102} cachedPath;
103
104struct bootCaches {
105    int cachefd;                // Sec: file descriptor to validate data
106    char bsdname[DEVMAXPATHSIZE]; // for passing to bless to get helpers
107    uuid_string_t fsys_uuid;    // optimized for cachedPaths (cf. 5114411, XX?)
108    CFStringRef csfde_uuid;     // encrypted volumes's LVF UUID
109    char defLabel[NAME_MAX];    // defaults to volume name
110    char root[ROOTPATH_MAX];    // struct's paths relative to this root
111    CFDictionaryRef cacheinfo;  // raw BootCaches.plist data (for archs, etc)
112    struct timespec bcTime;     // cache the timestamp of bootcaches.plist
113
114    char kernelpath[BCPATH_MAX]; // path to kernel file (watch only)
115                                 // <= 10.9 - /Volumes/foo/mach_kernel
116                                 // > 10.9 - /Volumes/foo/System/Library/Kernels/kernel
117    int  nexts;                 // number of extensions directory paths
118    char *exts;                 // null terminated extensions dir paths
119    char locSource[BCPATH_MAX]; // only EFILogin.framework/Resources for now
120    char locPref[BCPATH_MAX];   // /L/P/.GlobalPreferences
121    char bgImage[BCPATH_MAX];   // /L/Caches/com.apple.desktop.admin.png
122    unsigned nrps;              // number of RPS paths in Apple_Boot
123    cachedPath *rpspaths;       // e.g. mkext, kernel, Boot.plist
124    unsigned nmisc;             // "other" files (non-critical)
125    cachedPath *miscpaths;      // e.g. icons, labels, etc
126    cachedPath efibooter;       // booters get their own paths
127    cachedPath ofbooter;        // (we have to bless them, etc)
128
129    // pointers to special watched paths (stored in arrays above)
130    cachedPath *kext_boot_cache_file;     // -> kernelcache
131    cachedPath *bootconfig;     // -> .../L/Prefs/SC/com.apple.Boot.plist
132    cachedPath *efidefrsrcs;    // -> usr/standalone/i386/EfiLoginUI
133    cachedPath *efiloccache;    // -> ...Caches/../EFILoginLocalizations
134    cachedPath *label;          // -> .../S/L/CS/.disk_label (in miscPaths)
135    cachedPath *erpropcache;    // crypto metadata gets special treatment
136    Boolean erpropTSOnly;       // whether props expected in root fsys
137#if DEV_KERNEL_SUPPORT
138    int kernelsCount;           // count of valid kernels in /System/Library/Kernels
139                                // This will be 0 for volumes that do not support
140                                // /System/Library/Kernels/.
141    int nekcp;                          // number of extraKernelCachePaths
142    cachedPath *extraKernelCachePaths;  // kernelcache files with suffix, may be NULL
143#endif
144};
145/* use sizeof() to get it the right bounds */
146#undef TSPATH_MAX
147#undef BCPATH_MAX
148#undef ROOTPATH_MAX
149
150// check and tweak Boot!=Root status
151Boolean hasBootRootBoots(struct bootCaches *caches, CFArrayRef *auxPartsCopy,
152                         CFArrayRef *dataPartsCopy, Boolean *isAPM);
153Boolean notBRDefault(const char *mount, const char *subdir);
154int markNotBRDefault(int scopefd, const char *mount, const char* subdir,
155                     Boolean marking);
156
157// Everything except vol_path is optional.
158// If specified, vol_bsd must point to at least DEVMAXPATHSIZE bytes.
159// If specified, vol_name must point to at least NAME_MAX bytes.
160// If no CoreStorage is detected and cslvf_uuid is non-NULL,
161// *cslvf_uuid will be set to NULL.
162int copyVolumeInfo(const char *vol_path, uuid_t *vol_uuid,
163                   CFStringRef *cslvf_uuid, char vol_bsd[DEVMAXPATHSIZE],
164                   char vol_name[NAME_MAX]);
165
166// no CSFDE data => encContext = NULL, timeStamp = 0LL;
167int copyCSFDEInfo(CFStringRef uuidStr, CFDictionaryRef *encContext,
168                   time_t *timeStamp);
169
170/* ctors / dtors */
171// for kextcache
172struct bootCaches* readBootCaches(char *volRoot, BRUpdateOpts_t opts);
173// and kextd
174struct bootCaches* readBootCachesForDADisk(DADiskRef dadisk);   // kextd
175// (Warning: these will create S/L/Caches/bootstamps if missing.)
176
177void destroyCaches(struct bootCaches *caches);
178DADiskRef createDiskForMount(DASessionRef session, const char *mount);
179
180// Check all cached paths vs. bootstamps
181Boolean needUpdates(struct bootCaches *caches, BRUpdateOpts_t opts,
182                    Boolean *rps, Boolean *booters, Boolean *misc,
183                    OSKextLogSpec oodLogSpec);
184
185/* When copying non-default content to a helper partition,
186   taintDefaultStamps() finds and taints any online volumes that own the
187   helper.  Once tainted, kextcache -u (called through Disk Management
188   by Startup Disk and the Installer) will notice that the helper contents
189   need to be replaced and will restore the volume and helper back to the
190   default configuration.  kextd ignores the taint in its checks, but if
191   something else changes, the kextcache -u launched by kextd *will*
192   notice the taint and copy everything instead of only what changed. */
193int taintDefaultStamps(CFStringRef targetBSD);
194
195// update the bootstamp files from the tstamps stored in the bootCaches struct
196#define kBCStampsUnlinkOnly 0           // updateStamps always unlinks
197#define kBCStampsApplyTimes 1           // apply stored timestamps
198int updateStamps(struct bootCaches *caches, int command);
199
200// check / rebuild kext caches needs rebuilding
201Boolean plistCachesNeedRebuild(const NXArchInfo * kernelArchInfo);
202Boolean check_kext_boot_cache_file(
203    struct bootCaches * caches,
204    const char * cache_path,
205    const char * kernel_path);
206// build the mkext; waiting for the kextcache child if instructed
207int rebuild_kext_boot_cache_file(
208    struct bootCaches *caches,
209    Boolean wait,
210    const char * cache_path,
211    const char * kernel_file);
212
213// check/rebuild CSFDE caches
214Boolean check_csfde(struct bootCaches *caches);
215int rebuild_csfde_cache(struct bootCaches *caches);
216int writeCSFDEProps(int scopefd, CFDictionaryRef ectx,
217                    char *cspvbsd, char *dstpath);
218Boolean check_loccache(struct bootCaches *caches);
219int rebuild_loccache(struct bootCaches *caches);
220
221// diskarb helpers
222void _daDone(DADiskRef disk, DADissenterRef dissenter, void *ctx);
223int updateMount(mountpoint_t mount, uint32_t mntgoal);
224
225
226pid_t launch_rebuild_all(char * rootPath, Boolean force, Boolean wait);
227
228#endif /* __BOOTCACHES_H__ */
229
230