1/* 2 * Copyright (c) 1991-2005 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28#include <sys/param.h> 29#include <sys/types.h> 30#include <sys/uio.h> 31#include <sys/vnode.h> 32#include <vm/vm_kern.h> 33#include <mach/kern_return.h> 34#include <mach/vm_param.h> 35#include <kern/cpu_number.h> 36#include <mach-o/fat.h> 37#include <kern/mach_loader.h> 38#include <kern/mach_fat.h> 39#include <libkern/OSByteOrder.h> 40#include <machine/exec.h> 41 42/********************************************************************** 43 * Routine: fatfile_getarch() 44 * 45 * Function: Locate the architecture-dependant contents of a fat 46 * file that match this CPU. 47 * 48 * Args: vp: The vnode for the fat file. 49 * header: A pointer to the fat file header. 50 * req_cpu_type: The required cpu type. 51 * mask_bits: Bits to mask from the sub-image type when 52 * grading it vs. the req_cpu_type 53 * archret (out): Pointer to fat_arch structure to hold 54 * the results. 55 * 56 * Returns: KERN_SUCCESS: Valid architecture found. 57 * KERN_FAILURE: No valid architecture found. 58 **********************************************************************/ 59static load_return_t 60fatfile_getarch( 61#if 0 62 struct vnode *vp, 63#else 64 __unused struct vnode *vp, 65#endif 66 vm_offset_t data_ptr, 67 cpu_type_t req_cpu_type, 68 cpu_type_t mask_bits, 69 struct fat_arch *archret) 70{ 71 /* vm_pager_t pager; */ 72 vm_offset_t addr; 73 vm_size_t size; 74 load_return_t lret; 75 struct fat_arch *arch; 76 struct fat_arch *best_arch; 77 int grade; 78 int best_grade; 79 int nfat_arch; 80 off_t end_of_archs; 81 cpu_type_t testtype; 82 cpu_type_t testsubtype; 83 struct fat_header *header; 84#if 0 85 off_t filesize; 86#endif 87 88 /* 89 * Get the pager for the file. 90 */ 91 92 header = (struct fat_header *)data_ptr; 93 94 /* 95 * Map portion that must be accessible directly into 96 * kernel's map. 97 */ 98 nfat_arch = OSSwapBigToHostInt32(header->nfat_arch); 99 100 end_of_archs = (off_t)nfat_arch * sizeof(struct fat_arch) + 101 sizeof(struct fat_header); 102#if 0 103 filesize = ubc_getsize(vp); 104 if (end_of_archs > (int)filesize) { 105 return(LOAD_BADMACHO); 106 } 107#endif 108 109 /* 110 * This check is limited on the top end because we are reading 111 * only PAGE_SIZE bytes 112 */ 113 if (end_of_archs > PAGE_SIZE || 114 end_of_archs < (off_t)(sizeof(struct fat_header)+sizeof(struct fat_arch))) 115 return(LOAD_BADMACHO); 116 117 /* 118 * Round size of fat_arch structures up to page boundry. 119 */ 120 size = round_page(end_of_archs); 121 if (size == 0) 122 return(LOAD_BADMACHO); 123 124 /* 125 * Scan the fat_arch's looking for the best one. */ 126 addr = data_ptr; 127 best_arch = NULL; 128 best_grade = 0; 129 arch = (struct fat_arch *) (addr + sizeof(struct fat_header)); 130 for (; nfat_arch-- > 0; arch++) { 131 testtype = OSSwapBigToHostInt32(arch->cputype); 132 testsubtype = OSSwapBigToHostInt32(arch->cpusubtype) & ~CPU_SUBTYPE_MASK; 133 134 /* 135 * Check to see if right cpu type. 136 */ 137 if((testtype & ~mask_bits) != (req_cpu_type & ~mask_bits)) { 138 continue; 139 } 140 141 /* 142 * Get the grade of the cpu subtype (without feature flags) 143 */ 144 grade = grade_binary(testtype, testsubtype); 145 146 /* 147 * Remember it if it's the best we've seen. 148 */ 149 if (grade > best_grade) { 150 best_grade = grade; 151 best_arch = arch; 152 } 153 } 154 155 /* 156 * Return our results. 157 */ 158 if (best_arch == NULL) { 159 lret = LOAD_BADARCH; 160 } else { 161 archret->cputype = 162 OSSwapBigToHostInt32(best_arch->cputype); 163 archret->cpusubtype = 164 OSSwapBigToHostInt32(best_arch->cpusubtype); 165 archret->offset = 166 OSSwapBigToHostInt32(best_arch->offset); 167 archret->size = 168 OSSwapBigToHostInt32(best_arch->size); 169 archret->align = 170 OSSwapBigToHostInt32(best_arch->align); 171 172 lret = LOAD_SUCCESS; 173 } 174 175 /* 176 * Free the memory we allocated and return. 177 */ 178 return(lret); 179} 180 181load_return_t 182fatfile_getarch_affinity( 183 struct vnode *vp, 184 vm_offset_t data_ptr, 185 struct fat_arch *archret, 186 int affinity __unused) 187{ 188 /* 189 * Ignore all architectural bits when determining if an image 190 * in a fat file should be skipped or graded. 191 */ 192 return fatfile_getarch(vp, data_ptr, cpu_type(), CPU_ARCH_MASK, archret); 193} 194 195/********************************************************************** 196 * Routine: fatfile_getarch_with_bits() 197 * 198 * Function: Locate the architecture-dependant contents of a fat 199 * file that match this CPU. 200 * 201 * Args: vp: The vnode for the fat file. 202 * archbits: Architecture specific feature bits 203 * header: A pointer to the fat file header. 204 * archret (out): Pointer to fat_arch structure to hold 205 * the results. 206 * 207 * Returns: KERN_SUCCESS: Valid architecture found. 208 * KERN_FAILURE: No valid architecture found. 209 **********************************************************************/ 210load_return_t 211fatfile_getarch_with_bits( 212 struct vnode *vp, 213 integer_t archbits, 214 vm_offset_t data_ptr, 215 struct fat_arch *archret) 216{ 217 return fatfile_getarch(vp, data_ptr, archbits | (cpu_type() & ~CPU_ARCH_MASK), 0, archret); 218} 219 220