first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,114 @@
|
||||
#include <lib/env.h>
|
||||
#include <stdlib.h>
|
||||
#include <lib/nvram.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <arch.h>
|
||||
|
||||
|
||||
#define BREADCRUMB_BUFFER_SIZE 256 // This is arbitrarily sized, should be large enough for
|
||||
// sensible options of key/value
|
||||
#define BREADCRUMB_MIN_SIZE 3 // Smallest size of a breadcrumb
|
||||
|
||||
typedef struct {
|
||||
char* buffer; // Storage for the breadcrumbs
|
||||
int buffer_len; // Length of breadcrumb buffer
|
||||
int wrpos; // Current write position
|
||||
} breadcrumb_store_t;
|
||||
|
||||
static bool initialized = false;
|
||||
|
||||
breadcrumb_store_t breadcrumb_store;
|
||||
|
||||
|
||||
static char* bc_cur_pos (void)
|
||||
{
|
||||
ASSERT(breadcrumb_store.wrpos <= breadcrumb_store.buffer_len);
|
||||
return &breadcrumb_store.buffer[breadcrumb_store.wrpos];
|
||||
}
|
||||
|
||||
static int bc_remaining (void)
|
||||
{
|
||||
ASSERT(breadcrumb_store.wrpos <= breadcrumb_store.buffer_len);
|
||||
return breadcrumb_store.buffer_len - breadcrumb_store.wrpos;
|
||||
}
|
||||
|
||||
void _platform_init_breadcrumbs_internal(void)
|
||||
{
|
||||
if (!initialized) {
|
||||
breadcrumb_store.buffer = malloc(BREADCRUMB_BUFFER_SIZE);
|
||||
breadcrumb_store.wrpos = 0;
|
||||
breadcrumb_store.buffer_len = BREADCRUMB_BUFFER_SIZE;
|
||||
|
||||
initialized = (breadcrumb_store.buffer != NULL);
|
||||
dprintf(DEBUG_INFO, "breadcrumb store initialized at %p\n", breadcrumb_store.buffer);
|
||||
platform_record_breadcrumb_marker("BOOT");
|
||||
}
|
||||
}
|
||||
|
||||
void _platform_record_breadcrumb_internal(const char* key, const char* val)
|
||||
{
|
||||
if (initialized && bc_remaining() > BREADCRUMB_MIN_SIZE) {
|
||||
int count = (int)snprintf(bc_cur_pos(), bc_remaining(), "%s=%s, ", key, val);
|
||||
|
||||
if (count > 0)
|
||||
breadcrumb_store.wrpos += strlen(bc_cur_pos());
|
||||
}
|
||||
}
|
||||
|
||||
void _platform_record_breadcrumb_marker_internal(const char* val)
|
||||
{
|
||||
if (initialized && bc_remaining() > BREADCRUMB_MIN_SIZE) {
|
||||
int count = (int)snprintf(bc_cur_pos(), bc_remaining(), "<%s> ", val);
|
||||
|
||||
if (count > 0)
|
||||
breadcrumb_store.wrpos += strlen(bc_cur_pos());
|
||||
}
|
||||
}
|
||||
|
||||
void _platform_record_breadcrumb_int_internal(const char* key, int val)
|
||||
{
|
||||
if (initialized && bc_remaining() > BREADCRUMB_MIN_SIZE) {
|
||||
int count = (int)snprintf(bc_cur_pos(), bc_remaining(), "%s=%d, ", key, val);
|
||||
|
||||
if (count > 0)
|
||||
breadcrumb_store.wrpos += strlen(bc_cur_pos());
|
||||
}
|
||||
}
|
||||
|
||||
void _platform_commit_breadcrumbs_internal(const char* envvar)
|
||||
{
|
||||
if (initialized) {
|
||||
platform_record_breadcrumb_marker("DONE");
|
||||
// We expect this buffer to always be NULL terminated since it was built using
|
||||
// snprintf(), but just to be sure, make sure the end of the buffer is terminated.
|
||||
breadcrumb_store.buffer[breadcrumb_store.buffer_len - 1] = '\0';
|
||||
|
||||
const char* existing_breadcrumbs = env_get(envvar);
|
||||
if (existing_breadcrumbs) {
|
||||
dprintf(DEBUG_INFO, "Existing breadcrumbs found: '%s'\n", existing_breadcrumbs);
|
||||
// If there's already iBoot breadcrumbs, we should preserve them chronologically
|
||||
// (earliest first). Since we need to prepend, we might as well swap it with
|
||||
// a new buffer.
|
||||
if (bc_remaining() < (int)strlen(existing_breadcrumbs)) {
|
||||
// Existing breadcrumbs would not fit. Drop the oldest breadcrumbs first
|
||||
existing_breadcrumbs += ((int)strlen(existing_breadcrumbs) - bc_remaining());
|
||||
}
|
||||
char* tmp_buf = malloc(BREADCRUMB_BUFFER_SIZE);
|
||||
if (tmp_buf) {
|
||||
int count = snprintf(tmp_buf, BREADCRUMB_BUFFER_SIZE, "%s%s", existing_breadcrumbs, breadcrumb_store.buffer);
|
||||
if (count >= 0 && count < BREADCRUMB_BUFFER_SIZE)
|
||||
breadcrumb_store.wrpos = count;
|
||||
else
|
||||
breadcrumb_store.wrpos = 0;
|
||||
|
||||
free(breadcrumb_store.buffer);
|
||||
breadcrumb_store.buffer = tmp_buf;
|
||||
}
|
||||
}
|
||||
dprintf(DEBUG_INFO, "Committing breadcrumbs [used %d of %d bytes]: Setting '%s'='%s'\n", breadcrumb_store.wrpos, breadcrumb_store.buffer_len, envvar, breadcrumb_store.buffer);
|
||||
env_set(envvar, breadcrumb_store.buffer, ENV_PERSISTENT);
|
||||
nvram_save();
|
||||
initialized=false; // Stop recording breadcrumbs and make redundant commits a no-op.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2008,2014-2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#if !APPLICATION_SECUREROM
|
||||
|
||||
#include <lib/mib.h>
|
||||
#include <platform.h>
|
||||
|
||||
// Default MIB Application/Product
|
||||
MIB_CONSTANT_WEAK(kMIBTargetApplicationProduct, kOIDTypeUInt32, 0);
|
||||
|
||||
// Default MIB build configuration constants
|
||||
MIB_CONSTANT_WEAK(kMIBTargetWithHwAsp, kOIDTypeBoolean, false);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetWithEffaceable, kOIDTypeBoolean, false);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetWithFileSystem, kOIDTypeBoolean, false);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetWithHwFlashNand, kOIDTypeBoolean, false);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetWithHwFlashNor, kOIDTypeBoolean, false);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetWithHwNvme, kOIDTypeBoolean, false);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetWithLegacyPanicLogs, kOIDTypeBoolean, false);
|
||||
|
||||
// Default MIB target paint constants
|
||||
MIB_CONSTANT_WEAK(kMIBTargetDisplayGammaTableCount, kOIDTypeUInt32, 0);
|
||||
MIB_CONSTANT_PTR_WEAK(kMIBTargetDisplayGammaTablePtr, kOIDTypeStruct, NULL);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetPanicOnUnknownDclrVersion, kOIDTypeBoolean, true);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetPictureScale, kOIDTypeUInt32, 1);
|
||||
|
||||
// Default MIB NOR configuration
|
||||
MIB_CONSTANT_WEAK(kMIBTargetNvramNorBankCount, kOIDTypeUInt32, 2);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetNvramNorBankSize, kOIDTypeSize, 0x2000);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetNvramNorOffset, kOIDTypeInt32, -(2 * 0x2000));
|
||||
|
||||
// Default MIB Image3 constants
|
||||
// Delete this and it's definition in mib.base when all Image3 targets are deprecated.
|
||||
MIB_CONSTANT_WEAK(kMIBTargetAcceptGlobalTicket, kOIDTypeBoolean, false);
|
||||
|
||||
//Default Color Manager Data
|
||||
MIB_CONSTANT_WEAK(kMIBTargetDisplayCMEngammaTablePtr, kOIDTypeStruct, NULL);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetDisplayCMEngammaTableCount, kOIDTypeUInt32, 0);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetDisplayCMDegammaTablePtr, kOIDTypeStruct, NULL);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetDisplayCMDegammaTableCount, kOIDTypeUInt32, 0);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetDisplayCMMatrixTablePtr, kOIDTypeStruct, NULL);
|
||||
MIB_CONSTANT_WEAK(kMIBTargetDisplayCMMatrixTableCount, kOIDTypeUInt32, 0);
|
||||
|
||||
#endif // !APPLICATION_SECUREROM
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
/* XXX keep this here but blank for now */
|
||||
@@ -0,0 +1,36 @@
|
||||
# Copyright (C) 2007 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
|
||||
LIBPGINDEP_DIR := $(GET_LOCAL_DIR)
|
||||
LIBPGINDEP_BUILD:= $(call TOLIBDIR,$(LIBPGINDEP_DIR)/LIBPGINDEP.a)
|
||||
COMMONLIBS += LIBPGINDEP
|
||||
|
||||
# Force this library's symbols to be imported so that they can't be
|
||||
# overridden. This library isn't designed with one function per object file
|
||||
# to allow selective overriding
|
||||
GLOBAL_LDFORCELIBS += $(LIBPGINDEP_BUILD)
|
||||
|
||||
# Only process the remainder of the makefile if we are building libraries
|
||||
#
|
||||
ifeq ($(MAKEPHASE),libraries)
|
||||
|
||||
LIBPGINDEP_OBJS := \
|
||||
$(LIBPGINDEP_DIR)/platform_indep.o \
|
||||
$(LIBPGINDEP_DIR)/target_indep.o \
|
||||
$(LIBPGINDEP_DIR)/target_pass_boot_manifest.o \
|
||||
$(LIBPGINDEP_DIR)/breadcrumbs.o
|
||||
|
||||
LIBPGINDEP_OBJS := $(call TOLIBOBJDIR,$(LIBPGINDEP_OBJS))
|
||||
|
||||
$(LIBPGINDEP_BUILD): $(LIBPGINDEP_OBJS)
|
||||
|
||||
ALL_DEPS += $(LIBPGINDEP_OBJS:%o=%d)
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#include <arch.h>
|
||||
#include <debug.h>
|
||||
#include <drivers/aes.h>
|
||||
#include <drivers/power.h>
|
||||
#if WITH_HW_SEP
|
||||
#include <drivers/sep/sep_client.h>
|
||||
#endif
|
||||
#if WITH_EFFACEABLE
|
||||
#include <lib/effaceable.h>
|
||||
#endif
|
||||
#include <lib/image.h>
|
||||
#include <lib/libc.h>
|
||||
#include <lib/nonce.h>
|
||||
#include <lib/random.h>
|
||||
#include <lib/syscfg.h>
|
||||
#include <platform.h>
|
||||
#include <platform/chipid.h>
|
||||
#include <platform/memmap.h>
|
||||
#include <target.h>
|
||||
#include <sys.h>
|
||||
#include <sys/boot.h>
|
||||
#include <sys/hash.h>
|
||||
#include <sys/security.h>
|
||||
#include <drivers/display.h>
|
||||
|
||||
// platfom_dep holds generic functions that are just defined once for all
|
||||
// platforms, and are expected to be rebuilt for every target/product
|
||||
|
||||
|
||||
#if !PLATFORM_VARIANT_IOP && !PLATFORM_VARIANT_AUDIO
|
||||
#if (defined(__arm__) || defined(__arm64__))
|
||||
# include <arch/arm/arm.h>
|
||||
|
||||
/*
|
||||
* Default implementation of platform_cache_operation(), assumes the ARM architecture
|
||||
* supplied functions are available and appropriate.
|
||||
*/
|
||||
void platform_cache_operation(int operation, void *address, u_int32_t length)
|
||||
{
|
||||
uintptr_t start, end;
|
||||
void (*func)(addr_t addr);
|
||||
|
||||
/* all we are willing to do in the panic case is clean the entire cache */
|
||||
if (unlikely(operation & CACHE_PANIC)) {
|
||||
if ((operation & CACHE_CLEAN) && (NULL == address) && (0 == length))
|
||||
arm_clean_dcache();
|
||||
return;
|
||||
}
|
||||
|
||||
/* disable interrupts as we don't want to be re-entered */
|
||||
enter_critical_section();
|
||||
|
||||
if ((0 == address) && (0 == length)) {
|
||||
|
||||
/* invalidating the entire cache guarantees a crash */
|
||||
ASSERT((operation & (CACHE_CLEAN | CACHE_INVALIDATE)) != CACHE_INVALIDATE);
|
||||
|
||||
/* whole-cache operations */
|
||||
switch(operation & (CACHE_CLEAN | CACHE_INVALIDATE)) {
|
||||
case CACHE_CLEAN:
|
||||
arm_clean_dcache();
|
||||
break;
|
||||
|
||||
case CACHE_CLEAN | CACHE_INVALIDATE:
|
||||
arm_clean_invalidate_dcache();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* ranged operations by line */
|
||||
start = (uintptr_t)address;
|
||||
end = start + length;
|
||||
switch (operation & (CACHE_CLEAN | CACHE_INVALIDATE)) {
|
||||
case CACHE_INVALIDATE:
|
||||
/*
|
||||
* Non-aligned range invalidate operations are illegal
|
||||
* as we may shoot something else sharing the line.
|
||||
*/
|
||||
ASSERT(0 == (start % CPU_CACHELINE_SIZE));
|
||||
ASSERT(0 == (length % CPU_CACHELINE_SIZE));
|
||||
|
||||
/* invalidate */
|
||||
func = arm_invalidate_dcache_line;
|
||||
break;
|
||||
|
||||
case CACHE_CLEAN:
|
||||
/* adjust start to the base of the cacheline */
|
||||
start &= ~(CPU_CACHELINE_SIZE - 1);
|
||||
func = arm_clean_dcache_line;
|
||||
break;
|
||||
|
||||
case CACHE_CLEAN | CACHE_INVALIDATE:
|
||||
/* adjust start to the base of the cacheline */
|
||||
start &= ~(CPU_CACHELINE_SIZE - 1);
|
||||
func = arm_clean_invalidate_dcache_line;
|
||||
break;
|
||||
default:
|
||||
func = NULL;
|
||||
}
|
||||
/* do it */
|
||||
if (likely(NULL != func))
|
||||
for (; start < end; start += CPU_CACHELINE_SIZE)
|
||||
func(start);
|
||||
}
|
||||
|
||||
/* write buffer is address-agnostic */
|
||||
if (operation & CACHE_DRAIN_WRITE_BUFFER)
|
||||
arm_drain_write_buffer();
|
||||
|
||||
#if defined(__arm64__)
|
||||
arm_memory_barrier();
|
||||
#endif
|
||||
|
||||
exit_critical_section();
|
||||
}
|
||||
|
||||
void platform_memory_barrier(void)
|
||||
{
|
||||
arm_memory_barrier();
|
||||
}
|
||||
|
||||
#else
|
||||
# error no architecture support for platform_cache_operation
|
||||
#endif /* ARCH_ARM */
|
||||
#endif // PLATFORM_VARIANT_IOP
|
||||
|
||||
|
||||
// iBoot Flags
|
||||
// Bit 0 - Restore host should send image capable of restore boot (a.k.a. iBEC).
|
||||
// Bit 1 - Restore host should send ticket to validate images
|
||||
// Bit 2 - Restore host should send Image4 images.
|
||||
// Bit 3 - Current status of Secure fuse bit
|
||||
// Bit 4 - Current status of Production fuse bit
|
||||
// Bit 5 - Restore host should send images with SHA2-384 hash
|
||||
|
||||
uint32_t platform_get_iboot_flags(void)
|
||||
{
|
||||
u_int32_t flag_summary = 0;
|
||||
|
||||
#if WITH_RESTORE_STRAP
|
||||
flag_summary |= (1 << 0);
|
||||
#endif
|
||||
|
||||
#if WITH_TICKET
|
||||
flag_summary |= (1 << 1);
|
||||
#endif
|
||||
|
||||
#if WITH_IMAGE4
|
||||
flag_summary |= (1 << 2);
|
||||
#endif
|
||||
|
||||
if (platform_get_secure_mode()) flag_summary |= (1 << 3);
|
||||
|
||||
if (platform_get_current_production_mode()) flag_summary |= (1 << 4);
|
||||
|
||||
#if WITH_SHA2_384
|
||||
flag_summary |= (1 << 5);
|
||||
#endif
|
||||
|
||||
return flag_summary;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_PRODUCT_ID
|
||||
#define PLATFORM_PRODUCT_ID {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
|
||||
#endif
|
||||
|
||||
const char* platform_get_product_id(void)
|
||||
{
|
||||
static const char product_id[] = PLATFORM_PRODUCT_ID;
|
||||
return product_id;
|
||||
}
|
||||
|
||||
u_int32_t platform_get_security_epoch(void)
|
||||
{
|
||||
#if WITH_IMAGE4
|
||||
return chipid_get_minimum_epoch();
|
||||
#else
|
||||
u_int32_t build_epoch = PLATFORM_SECURITY_EPOCH;
|
||||
u_int32_t minimum_epoch = chipid_get_minimum_epoch();
|
||||
|
||||
if (minimum_epoch < build_epoch) minimum_epoch = build_epoch;
|
||||
|
||||
return minimum_epoch;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef DEFAULT_RECOVERY_MODE_PRODUCT_ID
|
||||
#define DEFAULT_RECOVERY_MODE_PRODUCT_ID 0x1281
|
||||
#endif
|
||||
|
||||
/*
|
||||
* platform_get_usb_product_id() - returns the usb product
|
||||
*
|
||||
*
|
||||
*/
|
||||
uint16_t platform_get_usb_product_id(void)
|
||||
{
|
||||
#if WITH_RECOVERY_MODE
|
||||
return DEFAULT_RECOVERY_MODE_PRODUCT_ID;
|
||||
#else
|
||||
return 0x1226 + (platform_get_security_domain() & 3);
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *platform_get_usb_product_string(void)
|
||||
{
|
||||
#if WITH_RECOVERY_MODE
|
||||
return "Apple Mobile Device (Recovery Mode)";
|
||||
#else
|
||||
return "Apple Mobile Device (DFU Mode)";
|
||||
#endif
|
||||
}
|
||||
|
||||
// gUSBSerialNumber Format: "CPID:xxxx CPRV:xx CPFM:xx SCEP:xx BDID:xx ECID:xxxxxxxxxxxxxxxx IBFL:xx"
|
||||
// optionally includes " SRTG:[<str24>]"
|
||||
// optionally includes " SRNM:[xxxxxxxxxxxxxxxx]"
|
||||
static char gUSBSerialNumber[127];
|
||||
// Size iBoot SecureROM
|
||||
// CPID (5 + 4) 9 9 9
|
||||
// CPRV + 1 + (5 + 2) 8 17 17
|
||||
// CPFM + 1 + (5 + 2) 8 25 25
|
||||
// SCEP + 1 + (5 + 2) 8 33 33
|
||||
// BDID + 1 + (5 + 2) 8 41 41
|
||||
// ECID + 1 + (5 + 16) 22 63 63
|
||||
// IBFL + 1 + (5 + 2) 8 71 71
|
||||
// SRTG + 1 + (5 + 2 + 24) 32 103
|
||||
// SRNM + 1 + (5 + 2 + 16) 24 95
|
||||
// nul + 1 1 96 104
|
||||
|
||||
static u_int32_t gUSBSerialNumberStatus;
|
||||
|
||||
const char *platform_get_usb_serial_number_string(bool full)
|
||||
{
|
||||
char srnm_buf[1 + (5 + 2 + 16) + 1];
|
||||
char imei_buf[1 + (5 + 2 + 16) + 1];
|
||||
char srtg_buf[1 + (5 + 2 + 24) + 1];
|
||||
int srnm_size = 0, imei_size = 0;
|
||||
|
||||
// Return if the request string has already been generated
|
||||
if (gUSBSerialNumberStatus > 1) return gUSBSerialNumber;
|
||||
if (!full && (gUSBSerialNumberStatus > 0)) return gUSBSerialNumber;
|
||||
|
||||
// Set the status based on the requested string
|
||||
gUSBSerialNumberStatus = full ? 2 : 1;
|
||||
|
||||
srtg_buf[0] = '\0';
|
||||
srnm_buf[srnm_size] = '\0';
|
||||
imei_buf[imei_size] = '\0';
|
||||
|
||||
snprintf(gUSBSerialNumber, sizeof(gUSBSerialNumber),
|
||||
"CPID:%04X CPRV:%02X CPFM:%02X SCEP:%02X BDID:%02X ECID:%016llX IBFL:%02X",
|
||||
platform_get_chip_id(), platform_get_chip_revision(), platform_get_fuse_modes(),
|
||||
platform_get_security_epoch(), platform_get_board_id(), platform_get_ecid_id(),
|
||||
platform_get_iboot_flags());
|
||||
|
||||
#if APPLICATION_SECUREROM
|
||||
snprintf(srtg_buf, sizeof(srtg_buf), " SRTG:[%s]", build_tag_string);
|
||||
strlcat(gUSBSerialNumber, srtg_buf, sizeof(gUSBSerialNumber));
|
||||
#endif
|
||||
|
||||
#if WITH_SYSCFG
|
||||
strlcpy(srnm_buf, " SRNM:[", sizeof(srnm_buf));
|
||||
srnm_size = syscfgCopyDataForTag('SrNm', (u_int8_t *)(srnm_buf + 7), 16);
|
||||
if (srnm_size > 0) {
|
||||
srnm_buf[7 + srnm_size] = '\0';
|
||||
strlcat(srnm_buf, "]", sizeof(srnm_buf));
|
||||
strlcat(gUSBSerialNumber, srnm_buf, sizeof(gUSBSerialNumber));
|
||||
}
|
||||
#endif
|
||||
|
||||
return gUSBSerialNumber;
|
||||
}
|
||||
|
||||
// gUSBMoreOther Format: ""
|
||||
// optionally includes " NONC:xxxxxxxxxxxxxxxx"
|
||||
// optionally includes " SNON:xxxxxxxxxxxxxxxx"
|
||||
static char gUSBMoreOther[127];
|
||||
// SHA1:
|
||||
// Size
|
||||
// NONC + 1 + (5 + (2*20)) 46
|
||||
// SNON + 1 + (5 + (2*20)) 46
|
||||
// Total 92
|
||||
//
|
||||
// SHA2-384:
|
||||
// Size
|
||||
// NONC + 1 + (5 + (2*32)) 70
|
||||
// SNON + 1 + (5 + (2*20)) 46
|
||||
// Total 116
|
||||
|
||||
static u_int32_t gUSBMoreOtherStatus;
|
||||
|
||||
const char *platform_get_usb_more_other_string(bool full)
|
||||
{
|
||||
u_int64_t nonc;
|
||||
u_int8_t nonc_hash[HASH_OUTPUT_SIZE];
|
||||
char nonc_buf[1 + (5 + (2 * NONCE_HASH_OUTPUT_SIZE)) + 1];
|
||||
u_int8_t i;
|
||||
|
||||
// Return if the request string has already been generated
|
||||
if (gUSBMoreOtherStatus > 1) return gUSBMoreOther;
|
||||
if (!full && (gUSBMoreOtherStatus > 0)) return gUSBMoreOther;
|
||||
|
||||
// Set the status based on the requested string
|
||||
gUSBMoreOtherStatus = full ? 2 : 1;
|
||||
|
||||
nonc_buf[0] = '\0';
|
||||
|
||||
gUSBMoreOther[0] = '\0';
|
||||
|
||||
if (full) {
|
||||
nonc = platform_get_nonce();
|
||||
hash_calculate((const void *)&nonc, sizeof(nonc), (void *)nonc_hash, sizeof(nonc_hash));
|
||||
|
||||
strlcpy(nonc_buf, " NONC:", sizeof(nonc_buf));
|
||||
for(i = 0; (i < NONCE_HASH_OUTPUT_SIZE) && (i < HASH_OUTPUT_SIZE); i++)
|
||||
snprintf((nonc_buf + 1 + 5 + (i * 2)), (sizeof(nonc_buf) - 1 - 5 - (i * 2)), "%02X", nonc_hash[i]);
|
||||
strlcat(gUSBMoreOther, nonc_buf, sizeof(gUSBMoreOther));
|
||||
|
||||
#if WITH_HW_SEP
|
||||
u_int8_t snon[SEP_NONCE_SIZE];
|
||||
if (platform_get_sep_nonce(snon) == 0) {
|
||||
|
||||
bzero(nonc_buf, sizeof(nonc_buf));
|
||||
strlcpy(nonc_buf, " SNON:", sizeof(nonc_buf));
|
||||
for(i = 0; (i < SEP_NONCE_SIZE); i++)
|
||||
snprintf((nonc_buf + 1 + 5 + (i * 2)), (sizeof(nonc_buf) - 1 - 5 - (i * 2)), "%02X", snon[i]);
|
||||
strlcat(gUSBMoreOther, nonc_buf, sizeof(gUSBMoreOther));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// dprintf(DEBUG_INFO, "%s, len=%ld\n", gUSBMoreOther, strlen(gUSBMoreOther));
|
||||
|
||||
return gUSBMoreOther;
|
||||
}
|
||||
|
||||
u_int64_t platform_consume_nonce(void)
|
||||
{
|
||||
uint64_t nonce = 0;
|
||||
const char* how = NULL;
|
||||
|
||||
#if WITH_EFFACEABLE
|
||||
if (effaceable_consume_nonce(&nonce)) {
|
||||
how = "effaced";
|
||||
}
|
||||
#elif WITH_NVRAM && WITH_ENV
|
||||
if (mobile_ap_nonce_consume_nonce(&nonce)) {
|
||||
how = "consumed";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WITH_RANDOM
|
||||
if (!how) {
|
||||
uint8_t *nonce_bytes = (uint8_t *)&nonce;
|
||||
int result = random_get_bytes(nonce_bytes, sizeof(nonce));
|
||||
RELEASE_ASSERT(result == 0);
|
||||
if (result == 0) {
|
||||
how = "generated";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!how) {
|
||||
nonce = 0;
|
||||
how = "zeroed";
|
||||
}
|
||||
|
||||
#if DEBUG_BUILD
|
||||
dprintf(DEBUG_INFO, "boot-nonce (%s): 0x%016llX\n", how, nonce);
|
||||
#endif
|
||||
|
||||
return nonce;
|
||||
}
|
||||
|
||||
size_t platform_get_display_memory_size(void)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
||||
struct display_info info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
display_get_info(&info);
|
||||
|
||||
if ((addr_t)info.framebuffer != 0)
|
||||
size = (uintptr_t)PANIC_BASE - (uintptr_t)info.framebuffer;
|
||||
#ifdef PURPLE_GFX_MEMORY_LEN
|
||||
if (size < PURPLE_GFX_MEMORY_LEN)
|
||||
size = PURPLE_GFX_MEMORY_LEN;
|
||||
#endif
|
||||
|
||||
return (size);
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <debug.h>
|
||||
#include <drivers/dram.h>
|
||||
#include <lib/libc.h>
|
||||
#include <platform.h>
|
||||
#include <platform/tunables.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// platfom_indep holds generic functions that are just defined once for all
|
||||
// platforms, and are not expected to be rebuilt for every target/product.
|
||||
//
|
||||
// These functions can vary per BUILD, and per architecture, but not per
|
||||
// PLATFORM, TARGET, PRODUCT, or CONFIG
|
||||
|
||||
void platform_not_supported(void)
|
||||
{
|
||||
dprintf(DEBUG_CRITICAL, "\n");
|
||||
dprintf(DEBUG_CRITICAL, "\n");
|
||||
dprintf(DEBUG_CRITICAL, "\n");
|
||||
dprintf(DEBUG_CRITICAL, "**************************************\n");
|
||||
dprintf(DEBUG_CRITICAL, "* *\n");
|
||||
dprintf(DEBUG_CRITICAL, "* This unit is not supported *\n");
|
||||
dprintf(DEBUG_CRITICAL, "* *\n");
|
||||
dprintf(DEBUG_CRITICAL, "**************************************\n");
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Fuse Modes
|
||||
// Bit 0 - Chip is Secure
|
||||
// Bit 1 - Chip is Production
|
||||
|
||||
uint32_t platform_get_fuse_modes(void)
|
||||
{
|
||||
u_int32_t fuse_summary = 0;
|
||||
|
||||
if (platform_get_secure_mode()) fuse_summary |= (1 << 0);
|
||||
|
||||
if (platform_get_raw_production_mode()) fuse_summary |= (1 << 1);
|
||||
|
||||
return fuse_summary;
|
||||
}
|
||||
|
||||
const char *platform_get_memory_manufacturer_string(void)
|
||||
{
|
||||
uint8_t index;
|
||||
|
||||
// This list is based of JEDEC Vendor list in dram.h
|
||||
// index 0 and 15 are reserverd, we are using them to provide additional information related to the system.
|
||||
static const char *memory_manufacturer_strings[JEDEC_NUM_MANUF_IDS] = {
|
||||
"Unknown",
|
||||
"Samsung",
|
||||
"Qimonda",
|
||||
"Elpida",
|
||||
"Etron",
|
||||
"Nanya",
|
||||
"Hynix",
|
||||
"Mosel",
|
||||
"Winbond",
|
||||
"ESMT",
|
||||
"Reserved",
|
||||
"Spansion",
|
||||
"SST",
|
||||
"ZMOS",
|
||||
"Intel",
|
||||
"Numonyx",
|
||||
"Micron",
|
||||
"FPGA",
|
||||
};
|
||||
|
||||
index = platform_get_memory_manufacturer_id();
|
||||
|
||||
if(platform_is_pre_lpddr4()) {
|
||||
|
||||
if (index >= JEDEC_NUM_MANUF_IDS)
|
||||
return NULL;
|
||||
|
||||
return memory_manufacturer_strings[index];
|
||||
} else {
|
||||
switch(index) {
|
||||
case JEDEC_LPDDR4_MANUF_ID_SAMSUNG:
|
||||
return "Samsung";
|
||||
break;
|
||||
|
||||
case JEDEC_LPDDR4_MANUF_ID_HYNIX:
|
||||
return "Hynix";
|
||||
break;
|
||||
|
||||
case JEDEC_LPDDR4_MANUF_ID_MICRON:
|
||||
return "Micron";
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uintptr_t platform_get_memory_region_base(memory_region_type_t region)
|
||||
{
|
||||
uintptr_t base = platform_get_memory_region_base_optional(region);
|
||||
if (base == (uintptr_t)-1)
|
||||
panic("unsupported region %d base requested\n", (int)region);
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
size_t platform_get_memory_region_size(memory_region_type_t region)
|
||||
{
|
||||
size_t size = platform_get_memory_region_size_optional(region);
|
||||
|
||||
if (size == (size_t)-1)
|
||||
panic("unsupported region %d size requested\n", region);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void platform_apply_tunables(const struct tunable_chip_struct *tunable_chips, uint32_t num_tunable_chips, const char* type)
|
||||
{
|
||||
const struct tunable_struct *tunable;
|
||||
uintptr_t base_address;
|
||||
uint32_t chip_rev = platform_get_chip_revision();
|
||||
uint32_t i;
|
||||
uint32_t t;
|
||||
bool match = false;
|
||||
|
||||
if (num_tunable_chips == 0)
|
||||
return;
|
||||
|
||||
ASSERT(tunable_chips != NULL);
|
||||
|
||||
// For each bucket of tunable values...
|
||||
for (i = 0; i < num_tunable_chips; i++) {
|
||||
|
||||
// Tunable for a newer chip revision?
|
||||
if (tunable_chips[i].chip_rev > chip_rev) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Tunable for an older chip revision?
|
||||
if (tunable_chips[i].chip_rev < chip_rev) {
|
||||
|
||||
if (match) {
|
||||
// We've already found all the tunables matching
|
||||
// this chip revision -- we're done.
|
||||
break;
|
||||
} else {
|
||||
// We haven't found a match yet. Because the tunable
|
||||
// chip table is supposed to be sorted from highest
|
||||
// to lowest, finding an older chip revision means
|
||||
// that there is no entry in the table for this
|
||||
// chip revision and we'll use the first older one
|
||||
// we find.
|
||||
dprintf(DEBUG_SPEW, "%s tunables for chip rev %d not found -- using tunables for chip rev %d\n",
|
||||
type, chip_rev, tunable_chips[i].chip_rev);
|
||||
chip_rev = tunable_chips[i].chip_rev;
|
||||
}
|
||||
}
|
||||
|
||||
// We've found a matching tunable chip revision (either an exact
|
||||
// match or the next older chip revision).
|
||||
match = true;
|
||||
|
||||
// Get the base address and pointer to the tunables data.
|
||||
tunable = tunable_chips[i].tunable;
|
||||
ASSERT(tunable != NULL);
|
||||
base_address = tunable_chips[i].base_address;
|
||||
|
||||
// For each tunable in registers at this base address...
|
||||
for (t = 0; tunable[t].offset != -1; t++) {
|
||||
|
||||
// Elided tunables have a size of zero, just skip them.
|
||||
if (tunable[t].size == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (tunable[t].size) {
|
||||
case sizeof(uint32_t):
|
||||
{
|
||||
volatile uint32_t *addr;
|
||||
uint32_t new_reg, old_reg, mask, value;
|
||||
|
||||
// Get the address of the register.
|
||||
addr = (volatile uint32_t *)(base_address + tunable[t].offset);
|
||||
|
||||
// Get the current value of the register.
|
||||
old_reg = *addr;
|
||||
mask = (uint32_t)tunable[t].mask;
|
||||
value = (uint32_t)tunable[t].value;
|
||||
|
||||
// If the tunable needs to be applied, do it.
|
||||
if ((old_reg & mask) != (value & mask)) {
|
||||
new_reg = old_reg;
|
||||
new_reg &= ~mask;
|
||||
new_reg |= value & mask;
|
||||
*addr = new_reg;
|
||||
dprintf(DEBUG_SPEW, "%s tunable addr/mask/value=%p/0x%08x/0x%08x: 0x%08x -> 0x%08x\n",
|
||||
type, addr, mask, value, old_reg, new_reg);
|
||||
} else {
|
||||
dprintf(DEBUG_SPEW, "%s tunable addr/mask/value=%p/0x%08x/0x%08x: already correct 0x%08x\n",
|
||||
type, addr, mask, value, old_reg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case sizeof(uint64_t):
|
||||
{
|
||||
volatile uint64_t *addr;
|
||||
uint64_t new_reg, old_reg, mask, value;
|
||||
|
||||
// Get the address of the register.
|
||||
addr = (volatile uint64_t *)(base_address + tunable[t].offset);
|
||||
|
||||
// Get the current value of the register.
|
||||
old_reg = *addr;
|
||||
mask = tunable[t].mask;
|
||||
value = tunable[t].value;
|
||||
|
||||
// If the tunable needs to be applied, do it.
|
||||
if ((old_reg & mask) != (value & mask)) {
|
||||
new_reg = old_reg;
|
||||
new_reg &= ~mask;
|
||||
new_reg |= value & mask;
|
||||
*addr = new_reg;
|
||||
dprintf(DEBUG_SPEW, "%s tunable addr/mask/value=%p/0x%016llx/0x%016llx: 0x%016llx -> 0x%016llx\n",
|
||||
type, addr, mask, value, old_reg, new_reg);
|
||||
} else {
|
||||
dprintf(DEBUG_SPEW, "%s tunable addr/mask/value=%p/0x%016llx/0x%016llx: already correct 0x%016llx\n",
|
||||
type, addr, mask, value, old_reg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
panic("Unsupported tunable register size");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *platform_apply_dt_tunables(const struct tunable_chip_struct *tunable_chips,
|
||||
uint32_t num_tunable_chips, uint8_t *buffer,
|
||||
uintptr_t dt_base, const char *type)
|
||||
{
|
||||
const struct tunable_struct *tunable;
|
||||
struct tunable_struct_unpacked tunable_data;
|
||||
uintptr_t addr;
|
||||
uintptr_t base_address;
|
||||
uint32_t chip_rev = platform_get_chip_revision();
|
||||
uint32_t i;
|
||||
uint32_t t;
|
||||
bool match = false;
|
||||
|
||||
if (num_tunable_chips == 0)
|
||||
return buffer;
|
||||
|
||||
ASSERT((tunable_chips != NULL) && (buffer != NULL));
|
||||
|
||||
// For each bucket of tunable values...
|
||||
for (i = 0; i < num_tunable_chips; i++) {
|
||||
|
||||
// Tunable for a newer chip revision?
|
||||
if (tunable_chips[i].chip_rev > chip_rev) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Tunable for an older chip revision?
|
||||
if (tunable_chips[i].chip_rev < chip_rev) {
|
||||
|
||||
if (match) {
|
||||
// We've already found all the tunables matching
|
||||
// this chip revision -- we're done.
|
||||
break;
|
||||
} else {
|
||||
// We haven't found a match yet. Because the tunable
|
||||
// chip table is supposed to be sorted from highest
|
||||
// to lowest, finding an older chip revision means
|
||||
// that there is no entry in the table for this
|
||||
// chip revision and we'll use the first older one
|
||||
// we find.
|
||||
dprintf(DEBUG_SPEW, "%s tunables for chip rev %d not found -- using tunables for chip rev %d\n",
|
||||
type, chip_rev, tunable_chips[i].chip_rev);
|
||||
chip_rev = tunable_chips[i].chip_rev;
|
||||
}
|
||||
}
|
||||
|
||||
// We've found a matching tunable chip revision (either an exact
|
||||
// match or the next older chip revision).
|
||||
match = true;
|
||||
|
||||
// Copy the tunable value and get the base address of the block it pertains to.
|
||||
tunable = tunable_chips[i].tunable;
|
||||
ASSERT(tunable != NULL);
|
||||
base_address = tunable_chips[i].base_address;
|
||||
|
||||
// For each tunable register at this base address...
|
||||
for (t = 0; tunable[t].offset != -1; t++) {
|
||||
|
||||
// Elided tunables have a size of zero, but pass them
|
||||
// through in case the driver wants to un-elide them.
|
||||
|
||||
// Copy the tunable data so we can update it.
|
||||
tunable_data.offset = tunable[t].offset;
|
||||
tunable_data.size = tunable[t].size;
|
||||
tunable_data.mask = tunable[t].mask;
|
||||
tunable_data.value = tunable[t].value;
|
||||
|
||||
addr = base_address + tunable_data.offset;
|
||||
|
||||
// Get the address of the register.
|
||||
if (dt_base != 0) {
|
||||
// Adjust the offset to match the reg property in the
|
||||
// device tree.
|
||||
tunable_data.offset = (uint32_t)addr - dt_base;
|
||||
ASSERT(tunable_data.offset != -1);
|
||||
}
|
||||
|
||||
if (tunable_data.size == -1) {
|
||||
dprintf(DEBUG_SPEW, "%s DT tunable @ 0x%lx: offset=0x%08x, size=%d, mask=0x%16llx, value=0x%16llx\n",
|
||||
type, addr,
|
||||
tunable_data.offset, tunable_data.size,
|
||||
tunable_data.mask, tunable_data.value);
|
||||
} else {
|
||||
dprintf(DEBUG_SPEW, "%s DT tunable @ 0x%lx: offset=0x%08x, size=%d, mask=0x%08llx, value=0x%08llx\n",
|
||||
type, addr,
|
||||
tunable_data.offset, tunable_data.size,
|
||||
tunable_data.mask, tunable_data.value);
|
||||
}
|
||||
memcpy(buffer, &tunable_data, sizeof(tunable_data));
|
||||
buffer += sizeof(tunable_data);
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include <platform/memmap.h>
|
||||
|
||||
/*
|
||||
* Utility file exporting symbols at absolute locations. These
|
||||
* values are largely useful to the build system before the final
|
||||
* object is linked, or for diagnosis purposes later.
|
||||
*/
|
||||
|
||||
/*
|
||||
* symbol <name> <value>
|
||||
*/
|
||||
.macro symbol
|
||||
.global $0
|
||||
.set $0 , $1
|
||||
.endmacro
|
||||
|
||||
/* This is used at link time */
|
||||
symbol _TEXT_BASE, TEXT_BASE
|
||||
|
||||
#if 0
|
||||
/* debug/sanity checks */
|
||||
symbol _INSECURE_MEMORY_BASE, INSECURE_MEMORY_BASE
|
||||
symbol _INSECURE_MEMORY_SIZE, INSECURE_MEMORY_SIZE
|
||||
symbol _DEFAULT_KERNEL_ADDRESS, DEFAULT_KERNEL_ADDRESS
|
||||
symbol _DEFAULT_KERNEL_SIZE, DEFAULT_KERNEL_SIZE
|
||||
symbol _DEFAULT_RAMDISK_ADDRESS, DEFAULT_RAMDISK_ADDRESS
|
||||
symbol _DEFAULT_RAMDISK_SIZE, DEFAULT_RAMDISK_SIZE
|
||||
symbol _DEFAULT_DEVICETREE_ADDRESS, DEFAULT_DEVICETREE_ADDRESS
|
||||
symbol _DEFAULT_DEVICETREE_SIZE, DEFAULT_DEVICETREE_SIZE
|
||||
|
||||
symbol _IBOOT_SIZE, IBOOT_SIZE
|
||||
symbol _MMU_TT_BASE, MMU_TT_BASE
|
||||
symbol _MMU_TT_SIZE, MMU_TT_SIZE
|
||||
symbol _STACK_BASE, STACK_BASE
|
||||
symbol _STACK_SIZE, STACK_SIZE
|
||||
#endif
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include <platform.h>
|
||||
#include <platform/pmgr.h>
|
||||
#include <debug.h>
|
||||
|
||||
static uint64_t pmgr_binning_read_register(uint64_t address, uint32_t low, uint32_t high, bool reg64)
|
||||
{
|
||||
uint64_t result = 0;
|
||||
do {
|
||||
uint64_t current_low;
|
||||
uint64_t offset;
|
||||
uint64_t register_value;
|
||||
|
||||
if (reg64) {
|
||||
offset = high/64;
|
||||
current_low = offset * 64;
|
||||
register_value = ((uint64_t *)(address))[offset];
|
||||
} else {
|
||||
offset = high/32;
|
||||
current_low = offset * 32;
|
||||
register_value = ((uint32_t *)(address))[offset];
|
||||
}
|
||||
|
||||
// Mask useful bit : [current_low:high]
|
||||
register_value &= (1ULL << (high - current_low + 1)) - 1;
|
||||
|
||||
if (current_low <= low) {
|
||||
result |= register_value >> (low - current_low);
|
||||
break;
|
||||
}
|
||||
|
||||
result |= register_value << (current_low - low);
|
||||
high = current_low - 1;
|
||||
} while (1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint64_t pmgr_binning_read(const struct pmgr_binning_fuse_to_register *fuse_to_register, uint32_t binning_low, uint32_t binning_high)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
while (1) {
|
||||
uint32_t i = 0;
|
||||
while (fuse_to_register[i].register_address != 0) {
|
||||
if ((fuse_to_register[i].binning_high >= binning_high) && (fuse_to_register[i].binning_low <= binning_high)) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (fuse_to_register[i].register_address == 0) {
|
||||
return PMGR_BINNING_NOTFOUND;
|
||||
}
|
||||
|
||||
if ((fuse_to_register[i].binning_high >= binning_high) && (fuse_to_register[i].binning_low <= binning_low)) {
|
||||
result |= pmgr_binning_read_register(fuse_to_register[i].register_address,
|
||||
binning_low - fuse_to_register[i].binning_low + fuse_to_register[i].register_low,
|
||||
binning_high - fuse_to_register[i].binning_low + fuse_to_register[i].register_low,
|
||||
fuse_to_register[i].register_64bit);
|
||||
break;
|
||||
}
|
||||
result |= pmgr_binning_read_register(fuse_to_register[i].register_address,
|
||||
fuse_to_register[i].register_low,
|
||||
binning_high - fuse_to_register[i].binning_low + fuse_to_register[i].register_low,
|
||||
fuse_to_register[i].register_64bit) << (fuse_to_register[i].binning_low - binning_low);
|
||||
binning_high = fuse_to_register[i].binning_low - 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t pmgr_binning_from_const_data(enum pmgr_binning_type_t type, uint32_t mode, bool use_binning)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < pmgr_binning_mode_to_const_data_size; i++) {
|
||||
if (pmgr_binning_mode_to_const_data[i].type != type) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_mode_to_const_data[i].mode != mode) {
|
||||
continue;
|
||||
}
|
||||
if ((use_binning) && pmgr_binning_mode_to_const_data[i].bingroup != pmgr_binning_get_group() && pmgr_binning_mode_to_const_data[i].bingroup != PMGR_BINNING_GROUP_ALL) {
|
||||
continue;
|
||||
}
|
||||
if ((use_binning) && (pmgr_binning_get_revision() < pmgr_binning_mode_to_const_data[i].fuse_revision_minimum)) {
|
||||
continue;
|
||||
}
|
||||
if ((!use_binning) && (pmgr_binning_mode_to_const_data[i].fuse_revision_minimum != 0)) {
|
||||
continue;
|
||||
}
|
||||
return pmgr_binning_mode_to_const_data[i].mv;
|
||||
}
|
||||
return PMGR_BINNING_NOTFOUND;
|
||||
}
|
||||
|
||||
uint32_t pmgr_binning_from_config_data(uint32_t voltage_index, const struct pmgr_binning_voltage_index_to_config **config_data)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < pmgr_binning_voltage_index_to_config_data_size; i++) {
|
||||
if (pmgr_binning_voltage_index_to_config_data[i].voltage_index != voltage_index) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_voltage_index_to_config_data[i].bingroup != pmgr_binning_get_group() && pmgr_binning_voltage_index_to_config_data[i].bingroup != PMGR_BINNING_GROUP_ALL) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_get_revision() < pmgr_binning_voltage_index_to_config_data[i].fuse_revision_minimum) {
|
||||
continue;
|
||||
}
|
||||
*config_data = &pmgr_binning_voltage_index_to_config_data[i];
|
||||
|
||||
return pmgr_binning_voltage_index_to_config_data[i].safe_voltage;
|
||||
}
|
||||
return PMGR_BINNING_NOTFOUND;
|
||||
}
|
||||
|
||||
int32_t pmgr_binning_get_voltage_offset(uint32_t voltage_index, enum pmgr_binning_type_t type)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t size = 0;
|
||||
const struct pmgr_binning_voltage_index_to_offset *voltage_index_to_offset;
|
||||
uint32_t board_id = platform_get_board_id();
|
||||
|
||||
for (i = 0; i < pmgr_binning_board_id_to_offsets_data_size; i++) {
|
||||
if (pmgr_binning_board_id_to_offsets_data[i].board_id != board_id) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_board_id_to_offsets_data[i].type != type) {
|
||||
continue;
|
||||
}
|
||||
if (platform_get_chip_revision() < pmgr_binning_board_id_to_offsets_data[i].chip_rev_min) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_board_id_to_offsets_data[i].bingroup != pmgr_binning_get_group() && pmgr_binning_board_id_to_offsets_data[i].bingroup != PMGR_BINNING_GROUP_ALL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
voltage_index_to_offset = pmgr_binning_board_id_to_offsets_data[i].voltage_offsets;
|
||||
size = pmgr_binning_board_id_to_offsets_data[i].size;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (voltage_index_to_offset[i].voltage_index != voltage_index) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_get_revision() < voltage_index_to_offset[i].fuse_revision_minimum) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return voltage_index_to_offset[i].offset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t pmgr_binning_mode_get_value(enum pmgr_binning_type_t type, uint32_t mode)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
do {
|
||||
if (pmgr_binning_mode_to_fuse_data[i].type == PMGR_BINNING_END_OF_LIST) {
|
||||
return PMGR_BINNING_NOTFOUND;
|
||||
}
|
||||
if (pmgr_binning_mode_to_fuse_data[i].type != type) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_mode_to_fuse_data[i].mode != mode) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (type != PMGR_BINNING_GROUP && pmgr_binning_mode_to_fuse_data[i].bingroup != pmgr_binning_get_group() && pmgr_binning_mode_to_fuse_data[i].bingroup != PMGR_BINNING_GROUP_ALL) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
if (pmgr_binning_mode_to_fuse_data[i].low > pmgr_binning_mode_to_fuse_data[i].high) {
|
||||
panic("Invalid low (%u) and high (%u) mode_to_fuse_data for type %u mode %u\n", pmgr_binning_mode_to_fuse_data[i].low, pmgr_binning_mode_to_fuse_data[i].high, type, mode);
|
||||
}
|
||||
|
||||
uint32_t result = pmgr_binning_read(pmgr_binning_mode_to_fuse_data[i].fuse_to_register, pmgr_binning_mode_to_fuse_data[i].low, pmgr_binning_mode_to_fuse_data[i].high);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t pmgr_binning_get_base(void)
|
||||
{
|
||||
static uint32_t base = 0;
|
||||
if (base == 0) {
|
||||
base = pmgr_binning_mode_get_value(PMGR_BINNING_BASE, 0);
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
uint32_t pmgr_binning_get_group(void)
|
||||
{
|
||||
static uint32_t group = 0;
|
||||
if (group == 0) {
|
||||
group =pmgr_binning_mode_get_value(PMGR_BINNING_GROUP, 0);
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
uint32_t pmgr_binning_get_revision(void)
|
||||
{
|
||||
static uint32_t revision = 0;
|
||||
if (revision == 0) {
|
||||
revision = pmgr_binning_mode_get_value(PMGR_BINNING_REV, 0);
|
||||
}
|
||||
return revision;
|
||||
}
|
||||
|
||||
uint32_t pmgr_binning_mode_get_mv(enum pmgr_binning_type_t type, uint32_t mode)
|
||||
{
|
||||
uint32_t value = pmgr_binning_mode_get_value(type, mode);
|
||||
if ((value == PMGR_BINNING_NOTFOUND) || (value == 0)) {
|
||||
return PMGR_BINNING_NOTFOUND;
|
||||
}
|
||||
return 25 * (pmgr_binning_get_base() + 1) + value * 5;
|
||||
}
|
||||
|
||||
uint32_t pmgr_binning_get_mv(uint32_t voltage_index, bool sram, bool use_binning)
|
||||
{
|
||||
uint32_t voltage;
|
||||
int32_t voltage_offset;
|
||||
uint32_t mode;
|
||||
enum pmgr_binning_type_t type;
|
||||
|
||||
if (sram) {
|
||||
if (voltage_index >= pmgr_binning_voltage_config_sram_data_size) {
|
||||
return PMGR_BINNING_NOTFOUND;
|
||||
}
|
||||
const struct pmgr_binning_voltage_config *binning_voltage_config;
|
||||
binning_voltage_config = &pmgr_binning_voltage_config_sram_data[voltage_index];
|
||||
|
||||
voltage = binning_voltage_config->safe_voltage;
|
||||
type = binning_voltage_config->type;
|
||||
mode = binning_voltage_config->mode;
|
||||
|
||||
if ((voltage == 0) && (type != PMGR_BINNING_NONE)){
|
||||
return pmgr_binning_from_const_data(type, mode, use_binning);
|
||||
}
|
||||
} else {
|
||||
const struct pmgr_binning_voltage_index_to_config *config_data;
|
||||
if (pmgr_binning_from_config_data(voltage_index, &config_data) == PMGR_BINNING_NOTFOUND) {
|
||||
return PMGR_BINNING_NOTFOUND;
|
||||
}
|
||||
|
||||
voltage = config_data->safe_voltage;
|
||||
type = config_data->type;
|
||||
mode = config_data->mode;
|
||||
|
||||
if (use_binning) {
|
||||
uint32_t voltage_binning = pmgr_binning_mode_get_mv(type, mode);
|
||||
if (voltage_binning != PMGR_BINNING_NOTFOUND) {
|
||||
voltage = voltage_binning;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
voltage_offset = pmgr_binning_get_voltage_offset(voltage_index, type);
|
||||
if ((int32_t)voltage + voltage_offset < 0) {
|
||||
panic("Invalid voltage offset");
|
||||
}
|
||||
|
||||
return voltage + voltage_offset;
|
||||
}
|
||||
|
||||
const struct pmgr_binning_vol_adj *pmgr_binning_get_vol_adj(uint32_t chipdid, uint32_t chip_rev, uint32_t voltage_index)
|
||||
{
|
||||
uint32_t fuse_rev = pmgr_binning_get_revision();
|
||||
|
||||
for (size_t i = 0; i < pmgr_binning_voltadj_entry_data_size; i++) {
|
||||
if (voltage_index != pmgr_binning_voltadj_entry_data[i].voltage_index) {
|
||||
continue;
|
||||
}
|
||||
if ((chip_rev < pmgr_binning_voltadj_entry_data[i].chip_rev_min)) {
|
||||
continue;
|
||||
}
|
||||
if ((fuse_rev < pmgr_binning_voltadj_entry_data[i].fuse_rev_min)) {
|
||||
continue;
|
||||
}
|
||||
return &pmgr_binning_voltadj_entry_data[i].voltages;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
|
||||
* Copyright (c) 2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#if !RELEASE_BUILD && WITH_MENU
|
||||
|
||||
#include <sys/menu.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <platform.h>
|
||||
#include <stdio.h>
|
||||
#include <sys.h>
|
||||
#include <lib/env.h>
|
||||
#include <platform/pmgr.h>
|
||||
|
||||
static bool pmgr_binning_menu_override_get_voltage_indexes(bool gpu, uint32_t *voltage_indexes, uint32_t voltage_index_size, uint32_t *voltage_index_found)
|
||||
{
|
||||
uint32_t freq = 0;
|
||||
uint32_t i = 0;
|
||||
const char *name = env_get(gpu?"pmgr_gpu_override":"pmgr_cpu_override");
|
||||
const struct pmgr_binning_voltage_index_to_config *config_data;
|
||||
*voltage_index_found = 0;
|
||||
if (name == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (i < voltage_index_size) {
|
||||
if (i > 0) {
|
||||
name = strchr(name, ',');
|
||||
if (name == NULL) {
|
||||
break;
|
||||
}
|
||||
name++;
|
||||
}
|
||||
|
||||
voltage_indexes[i] = atoi(name);
|
||||
if (pmgr_binning_from_config_data(voltage_indexes[i], &config_data) == PMGR_BINNING_NOTFOUND) {
|
||||
return false;
|
||||
}
|
||||
if ((gpu) && (config_data->type != PMGR_BINNING_GPU)) {
|
||||
return false;
|
||||
}
|
||||
if ((!gpu) && (config_data->type != PMGR_BINNING_CPU)) {
|
||||
return false;
|
||||
}
|
||||
freq = pmgr_platform_get_freq(gpu, voltage_indexes[i]);
|
||||
if (freq == 0) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
*voltage_index_found = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pmgr_binning_menu_find_safe_voltage(enum pmgr_binning_type_t type, uint32_t mode,
|
||||
uint32_t *safe_voltage, uint32_t *freq)
|
||||
{
|
||||
uint32_t i;
|
||||
*freq = 0;
|
||||
for (i = 0; i < pmgr_binning_voltage_config_sram_data_size; i++) {
|
||||
if (pmgr_binning_voltage_config_sram_data[i].mode != mode) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_voltage_config_sram_data[i].type != type) {
|
||||
continue;
|
||||
}
|
||||
*safe_voltage = pmgr_binning_voltage_config_sram_data[i].safe_voltage;
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < pmgr_binning_voltage_index_to_config_data_size; i++) {
|
||||
if (pmgr_binning_voltage_index_to_config_data[i].mode != mode) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_voltage_index_to_config_data[i].type != type) {
|
||||
continue;
|
||||
}
|
||||
if (type == PMGR_BINNING_CPU) {
|
||||
*freq = pmgr_platform_get_freq(false, pmgr_binning_voltage_index_to_config_data[i].voltage_index);
|
||||
} else if (type == PMGR_BINNING_GPU) {
|
||||
*freq = pmgr_platform_get_freq(true, pmgr_binning_voltage_index_to_config_data[i].voltage_index);
|
||||
}
|
||||
*safe_voltage = pmgr_binning_voltage_index_to_config_data[i].safe_voltage;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void pmgr_binning_menu_print_type(enum pmgr_binning_type_t type)
|
||||
{
|
||||
uint32_t mode;
|
||||
for (mode = 1; mode < 63; mode++) {
|
||||
uint32_t result = pmgr_binning_mode_get_value(type, mode);
|
||||
uint32_t safe_voltage;
|
||||
uint32_t freq;
|
||||
if ((result == PMGR_BINNING_NOTFOUND) || (result == 0)) {
|
||||
continue;
|
||||
}
|
||||
printf(" mode %u %u mV (0x%x)", mode, pmgr_binning_mode_get_mv(type, mode), pmgr_binning_mode_get_value(type, mode));
|
||||
|
||||
if (!pmgr_binning_menu_find_safe_voltage(type, mode, &safe_voltage, &freq)) {
|
||||
printf(" no safe voltage");
|
||||
} else {
|
||||
printf(" safe voltage %u mV", safe_voltage);
|
||||
}
|
||||
|
||||
if (freq > 0) {
|
||||
printf(" %u MHz", freq);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void pmgr_binning_menu_voltage_config_print(const struct pmgr_binning_voltage_config *voltage_config, uint32_t voltage_index)
|
||||
{
|
||||
const char *name = "";
|
||||
uint32_t freq = 0, safe_voltage = 0, mode = 0, type = 0;
|
||||
bool sram = false;
|
||||
|
||||
if (voltage_config != NULL) {
|
||||
safe_voltage = voltage_config->safe_voltage;
|
||||
mode = voltage_config->mode;
|
||||
type = voltage_config->type;
|
||||
}
|
||||
else {
|
||||
const struct pmgr_binning_voltage_index_to_config *config_data;
|
||||
if (pmgr_binning_from_config_data(voltage_index, &config_data) == PMGR_BINNING_NOTFOUND) {
|
||||
return;
|
||||
}
|
||||
safe_voltage = config_data->safe_voltage;
|
||||
mode = config_data->mode;
|
||||
type = config_data->type;
|
||||
}
|
||||
if (type == PMGR_BINNING_NONE) {
|
||||
return;
|
||||
}
|
||||
switch (type) {
|
||||
case PMGR_BINNING_CPU:
|
||||
name = "CPU";
|
||||
freq = pmgr_platform_get_freq(false, voltage_index);
|
||||
break;
|
||||
case PMGR_BINNING_GPU:
|
||||
name = "GPU";
|
||||
freq = pmgr_platform_get_freq(true, voltage_index);
|
||||
break;
|
||||
case PMGR_BINNING_SOC:
|
||||
name = "SOC";
|
||||
break;
|
||||
case PMGR_BINNING_CPU_SRAM:
|
||||
name = "CPU SRAM";
|
||||
sram = true;
|
||||
break;
|
||||
case PMGR_BINNING_GPU_SRAM:
|
||||
name = "GPU SRAM";
|
||||
sram = true;
|
||||
break;
|
||||
case PMGR_BINNING_SRAM:
|
||||
name = "SRAM";
|
||||
sram = true;
|
||||
break;
|
||||
default:
|
||||
name = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
printf(" %s index %u safe voltage %u mV",
|
||||
name,
|
||||
voltage_index,
|
||||
pmgr_binning_get_mv(voltage_index, sram, false));
|
||||
|
||||
if (pmgr_binning_mode_get_mv(type, mode) != PMGR_BINNING_NOTFOUND) {
|
||||
printf(" binning %u mV", pmgr_binning_get_mv(voltage_index, sram, true));
|
||||
} else {
|
||||
printf(" no binning %u mV", pmgr_binning_get_mv(voltage_index, sram, true));
|
||||
}
|
||||
|
||||
printf(" offset %d mV", pmgr_binning_get_voltage_offset(voltage_index, type));
|
||||
|
||||
if (mode != PMGR_BINNING_MODE_NONE && mode > 0) {
|
||||
printf(" mode %u", mode);
|
||||
}
|
||||
|
||||
if (freq > 0) {
|
||||
printf(" %u MHz", freq);
|
||||
}
|
||||
|
||||
if (sram && safe_voltage == 0) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < pmgr_binning_mode_to_const_data_size; i++) {
|
||||
if (pmgr_binning_mode_to_const_data[i].type != type) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_mode_to_const_data[i].mode != mode) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_mode_to_const_data[i].bingroup != pmgr_binning_get_group() && pmgr_binning_mode_to_const_data[i].bingroup != PMGR_BINNING_GROUP_ALL) {
|
||||
continue;
|
||||
}
|
||||
printf(" fuse >= %d %d mV", pmgr_binning_mode_to_const_data[i].fuse_revision_minimum, pmgr_binning_mode_to_const_data[i].mv + pmgr_binning_get_voltage_offset(voltage_index, type));
|
||||
}
|
||||
}
|
||||
else if (!sram && mode != PMGR_BINNING_MODE_NONE) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < pmgr_binning_voltage_index_to_config_data_size; i++) {
|
||||
if (pmgr_binning_voltage_index_to_config_data[i].voltage_index != voltage_index) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_voltage_index_to_config_data[i].type != type) {
|
||||
continue;
|
||||
}
|
||||
if (pmgr_binning_voltage_index_to_config_data[i].bingroup != pmgr_binning_get_group() && pmgr_binning_voltage_index_to_config_data[i].bingroup != PMGR_BINNING_GROUP_ALL) {
|
||||
continue;
|
||||
}
|
||||
printf(" fuse >= %d %d mV", pmgr_binning_voltage_index_to_config_data[i].fuse_revision_minimum, pmgr_binning_voltage_index_to_config_data[i].safe_voltage + pmgr_binning_get_voltage_offset(voltage_index, type));
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void pmgr_binning_menu_current_values_type(enum pmgr_binning_type_t type)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t freq;
|
||||
uint32_t voltage;
|
||||
while (pmgr_platform_get_perf_state(type, i, &voltage, &freq)) {
|
||||
if (freq == 0) {
|
||||
printf(" state %u: %u mV", i, voltage);
|
||||
} else {
|
||||
printf(" state %u: %u Mhz %u mV", i, freq / 1000000, voltage);
|
||||
}
|
||||
if ((type == PMGR_BINNING_CPU) && (pmgr_platform_get_perf_state(PMGR_BINNING_CPU_SRAM, i, &voltage, &freq))) {
|
||||
printf(" SRAM %u mV", voltage);
|
||||
}
|
||||
if ((type == PMGR_BINNING_GPU) && (pmgr_platform_get_perf_state(PMGR_BINNING_GPU_SRAM, i, &voltage, &freq))) {
|
||||
printf(" SRAM %u mV", voltage);
|
||||
}
|
||||
printf("\n");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static int do_pmgr(int argc, struct cmd_arg *args)
|
||||
{
|
||||
uint32_t voltage_indexes[32];
|
||||
uint32_t max_voltage_index = 0;
|
||||
uint32_t voltage_index_found;
|
||||
if ((argc < 2) || ((strcmp(args[1].str, "binning") != 0) && (strcmp(args[1].str, "values") != 0))) {
|
||||
printf("Usage\n");
|
||||
printf(" pmgr [values | [binning [internal|values]]]\n");
|
||||
printf(" pmgr binning: fused value\n");
|
||||
printf(" pmgr binning internal: fused value and all known operating points\n");
|
||||
printf(" pmgr values: values currently set in PMGR/ACC registers\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((argc > 1) && (strcmp(args[1].str, "values") == 0)) {
|
||||
printf("CPU:\n");
|
||||
pmgr_binning_menu_current_values_type(PMGR_BINNING_CPU);
|
||||
printf("GPU:\n");
|
||||
pmgr_binning_menu_current_values_type(PMGR_BINNING_GPU);
|
||||
printf("SOC:\n");
|
||||
pmgr_binning_menu_current_values_type(PMGR_BINNING_SOC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Fuse revision %u base %u bin group %u\n", pmgr_binning_get_revision(), pmgr_binning_get_base(), pmgr_binning_get_group());
|
||||
printf(" CPU\n");
|
||||
pmgr_binning_menu_print_type(PMGR_BINNING_CPU);
|
||||
printf(" CPU SRAM\n");
|
||||
pmgr_binning_menu_print_type(PMGR_BINNING_CPU_SRAM);
|
||||
printf(" GPU\n");
|
||||
pmgr_binning_menu_print_type(PMGR_BINNING_GPU);
|
||||
printf(" GPU SRAM\n");
|
||||
pmgr_binning_menu_print_type(PMGR_BINNING_GPU_SRAM);
|
||||
printf(" SRAM\n");
|
||||
pmgr_binning_menu_print_type(PMGR_BINNING_SRAM);
|
||||
printf(" SOC\n");
|
||||
pmgr_binning_menu_print_type(PMGR_BINNING_SOC);
|
||||
|
||||
if ((argc > 2) && (strcmp(args[2].str, "internal") == 0)) {
|
||||
uint32_t i;
|
||||
printf("\n");
|
||||
for (i = 0; i < pmgr_binning_voltage_index_to_config_data_size; i++) {
|
||||
if (pmgr_binning_voltage_index_to_config_data[i].voltage_index > max_voltage_index) {
|
||||
max_voltage_index = pmgr_binning_voltage_index_to_config_data[i].voltage_index;
|
||||
}
|
||||
}
|
||||
for (i = 0; i <= max_voltage_index; i++) {
|
||||
pmgr_binning_menu_voltage_config_print(NULL, i);
|
||||
}
|
||||
for (i = 0; i < pmgr_binning_voltage_config_sram_data_size; i++) {
|
||||
pmgr_binning_menu_voltage_config_print(&pmgr_binning_voltage_config_sram_data[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
if (pmgr_binning_menu_override_get_voltage_indexes(false, voltage_indexes, sizeof(voltage_indexes)/sizeof(voltage_indexes[0]), &voltage_index_found)) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < voltage_index_found; i++) {
|
||||
if (i == 0) {
|
||||
printf("\n\nOverridden CPU states:\n");
|
||||
}
|
||||
printf(" state %u ", i + 3); // state 0 (bypass), 1 (securerom) and 2 (current state) are not overridden
|
||||
pmgr_binning_menu_voltage_config_print(NULL, voltage_indexes[i]);
|
||||
}
|
||||
}
|
||||
if (pmgr_binning_menu_override_get_voltage_indexes(true, voltage_indexes, sizeof(voltage_indexes)/sizeof(voltage_indexes[0]), &voltage_index_found)) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < voltage_index_found; i++) {
|
||||
if (i == 0) {
|
||||
printf("\n\nOverridden GPU states:\n");
|
||||
}
|
||||
printf(" state %u ", i + 1); // state 0 (off) are not overridden
|
||||
pmgr_binning_menu_voltage_config_print(NULL, voltage_indexes[i]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pmgr_binning_menu_update_states(void)
|
||||
{
|
||||
uint32_t voltage_indexes[32];
|
||||
uint32_t voltage_index_found;
|
||||
|
||||
if (pmgr_binning_menu_override_get_voltage_indexes(false, voltage_indexes, sizeof(voltage_indexes)/sizeof(voltage_indexes[0]), &voltage_index_found)) {
|
||||
pmgr_platform_set_perf_state(false, 3, voltage_indexes, voltage_index_found);
|
||||
}
|
||||
if (pmgr_binning_menu_override_get_voltage_indexes(true, voltage_indexes, sizeof(voltage_indexes)/sizeof(voltage_indexes[0]), &voltage_index_found)) {
|
||||
pmgr_platform_set_perf_state(true, 1, voltage_indexes, voltage_index_found);
|
||||
}
|
||||
}
|
||||
|
||||
// _command, _function, _help, _meta
|
||||
MENU_COMMAND_DEVELOPMENT(pmgr, do_pmgr, "Print pmgr data", NULL);
|
||||
|
||||
#endif // !RELEASE_BUILD && WITH_MENU
|
||||
@@ -0,0 +1,42 @@
|
||||
# Copyright (C) 2015 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
# All H8+ chip must use pmgr_binning
|
||||
PMGR_BINNING=0
|
||||
|
||||
ifeq ($(SUB_PLATFORM),s8000)
|
||||
PMGR_BINNING=1
|
||||
endif
|
||||
|
||||
ifeq ($(SUB_PLATFORM),s8001)
|
||||
PMGR_BINNING=1
|
||||
endif
|
||||
|
||||
ifeq ($(SUB_PLATFORM),s8003)
|
||||
PMGR_BINNING=1
|
||||
endif
|
||||
|
||||
ifeq ($(PMGR_BINNING),1)
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/pmgr_binning.o
|
||||
|
||||
ifneq ($(BUILD),RELEASE)
|
||||
ifeq ($(PRODUCT),iBoot)
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/pmgr_binning_menu.o
|
||||
endif
|
||||
ifeq ($(PRODUCT),iBEC)
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/pmgr_binning_menu.o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Copyright (C) 2007-2013 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
#
|
||||
# Objects that must be built for every target.
|
||||
#
|
||||
# Adding files here is very expensive, as each file
|
||||
# gets compiled for every target/product/build permutation.
|
||||
#
|
||||
#
|
||||
|
||||
ifneq ($(APPLICATION),SecureROM)
|
||||
MODULES += \
|
||||
$(LOCAL_DIR)/pmgr
|
||||
endif
|
||||
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/default_mib.o \
|
||||
$(LOCAL_DIR)/platform_info.o \
|
||||
$(LOCAL_DIR)/platform_dep.o \
|
||||
$(LOCAL_DIR)/target_dep.o
|
||||
|
||||
# Include library with platform/target/product-independent functions
|
||||
LIBRARY_MODULES += $(LOCAL_DIR)
|
||||
|
||||
#
|
||||
# The platform_info file contains symbols with useful information
|
||||
#
|
||||
INFO_SYMBOL_FILE := $(call TOBUILDDIR,$(LOCAL_DIR)/platform_info.o)
|
||||
|
||||
# for platform_get_security_epoch()
|
||||
ifeq ($(DEVMAP_EPOCH),)
|
||||
OPTIONS += PLATFORM_SECURITY_EPOCH=00
|
||||
else
|
||||
OPTIONS += PLATFORM_SECURITY_EPOCH=$(DEVMAP_EPOCH)
|
||||
endif
|
||||
|
||||
ifneq ($(DEVMAP_PRODUCT_ID),)
|
||||
OPTIONS += PLATFORM_PRODUCT_ID=`echo $(DEVMAP_PRODUCT_ID) | sed 's/../0x&,/g' | sed 's/.*/{&}/g'`
|
||||
endif
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include <lib/syscfg.h>
|
||||
#include <lib/env.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Target/product dependent functions that aren't expected to be overridden by targets
|
||||
|
||||
bool target_is_tethered(void)
|
||||
{
|
||||
#if WITH_SYSCFG
|
||||
uint8_t tethcfg[16];
|
||||
|
||||
if ((syscfgCopyDataForTag('Teth', tethcfg, 16) != -1) && (tethcfg[0] != 0x0)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0 != env_get_uint("is-tethered", 0);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include <platform.h>
|
||||
#include <stdbool.h>
|
||||
#include <target.h>
|
||||
|
||||
bool target_config_ap(void)
|
||||
{
|
||||
static bool valid = false;
|
||||
static bool result;
|
||||
|
||||
if (!valid) {
|
||||
result = (platform_get_board_id() & 1) == 0;
|
||||
valid = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool target_config_dev(void)
|
||||
{
|
||||
static bool valid = false;
|
||||
static bool result;
|
||||
|
||||
if (!valid) {
|
||||
result = (platform_get_board_id() & 1) != 0;
|
||||
valid = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#include <target.h>
|
||||
#include <stdlib.h>
|
||||
#include <lib/devicetree.h>
|
||||
#include <lib/image4_spi.h>
|
||||
#include <debug.h>
|
||||
|
||||
/**
|
||||
* Stash away properties in a simple data structure while the image is being validated.
|
||||
*
|
||||
* The image4 wrapper extracts out properties before declaring an overall image valid/invalid,
|
||||
* and we also can load the kernelcache before the device tree.
|
||||
*/
|
||||
#define N_BOOL_PROPS 20
|
||||
#define N_INT_PROPS 20
|
||||
#define N_STRING_PROPS 10
|
||||
#define MAX_IMG4_STRING_LEN 64
|
||||
typedef struct {
|
||||
uint32_t tag;
|
||||
bool val;
|
||||
} bool_prop_t;
|
||||
typedef struct {
|
||||
uint32_t tag;
|
||||
uint64_t val;
|
||||
} int_prop_t;
|
||||
typedef struct {
|
||||
uint32_t tag;
|
||||
size_t length;
|
||||
uint8_t data[MAX_IMG4_STRING_LEN];
|
||||
} string_prop_t;
|
||||
|
||||
typedef struct {
|
||||
bool_prop_t bool_props[N_BOOL_PROPS];
|
||||
int_prop_t int_props[N_INT_PROPS];
|
||||
string_prop_t string_props[N_STRING_PROPS];
|
||||
|
||||
} image4_property_collection_t;
|
||||
|
||||
struct {
|
||||
bool is_valid;
|
||||
bool cb_encountered_error;
|
||||
image4_property_collection_t manifest_properties;
|
||||
image4_property_collection_t manifest_object_properties;
|
||||
} image4_properties;
|
||||
|
||||
static bool image4_start_cb(uint32_t type)
|
||||
{
|
||||
return (type == IMAGE_TYPE_KERNELCACHE || type == IMAGE_TYPE_KERNELCACHE_RESTORE);
|
||||
}
|
||||
static void image4_update_validity(bool is_valid)
|
||||
{
|
||||
if (!is_valid) {
|
||||
bzero(&image4_properties, sizeof(image4_properties));
|
||||
}
|
||||
image4_properties.is_valid = is_valid;
|
||||
}
|
||||
static void image4_bool_cb(uint32_t tag, bool is_object_property, bool val)
|
||||
{
|
||||
bool_prop_t* properties = NULL;
|
||||
if (is_object_property) {
|
||||
properties = image4_properties.manifest_object_properties.bool_props;
|
||||
} else {
|
||||
properties = image4_properties.manifest_properties.bool_props;
|
||||
}
|
||||
|
||||
for(int i = 0; i < N_BOOL_PROPS; i++)
|
||||
{
|
||||
if(properties[i].tag == 0)
|
||||
{
|
||||
properties[i].tag = tag;
|
||||
properties[i].val = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
dprintf(DEBUG_CRITICAL, "Ran out of space storing boolean properties -- please tune N_BOOL_PROPS");
|
||||
image4_properties.cb_encountered_error = true;
|
||||
}
|
||||
static void image4_int_cb(uint32_t tag, bool is_object_property, uint64_t val)
|
||||
{
|
||||
int_prop_t* properties = NULL;
|
||||
if (is_object_property) {
|
||||
properties = image4_properties.manifest_object_properties.int_props;
|
||||
} else {
|
||||
properties = image4_properties.manifest_properties.int_props;
|
||||
}
|
||||
|
||||
for(int i = 0; i < N_INT_PROPS; i++)
|
||||
{
|
||||
if(properties[i].tag == 0)
|
||||
{
|
||||
properties[i].tag = tag;
|
||||
properties[i].val = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
dprintf(DEBUG_CRITICAL, "Ran out of space storing integer properties -- please tune N_INT_PROPS");
|
||||
image4_properties.cb_encountered_error = true;
|
||||
}
|
||||
static void image4_string_cb(uint32_t tag, bool is_object_property, uint8_t* data, size_t length)
|
||||
{
|
||||
string_prop_t* properties = NULL;
|
||||
if (is_object_property) {
|
||||
properties = image4_properties.manifest_object_properties.string_props;
|
||||
} else {
|
||||
properties = image4_properties.manifest_properties.string_props;
|
||||
}
|
||||
|
||||
for(int i = 0; i < N_STRING_PROPS; i++)
|
||||
{
|
||||
if(properties[i].tag == 0)
|
||||
{
|
||||
if (length > MAX_IMG4_STRING_LEN) {
|
||||
dprintf(DEBUG_CRITICAL, "image4_string_cb: Property length %lu exceeds max supported length, %u", length, MAX_IMG4_STRING_LEN);
|
||||
image4_properties.cb_encountered_error = true;
|
||||
return;
|
||||
}
|
||||
properties[i].tag = tag;
|
||||
memcpy(properties[i].data, data, length);
|
||||
properties[i].length = length;
|
||||
return;
|
||||
}
|
||||
}
|
||||
dprintf(DEBUG_CRITICAL, "Ran out of space storing string properties -- please tune N_STRING_PROPS");
|
||||
image4_properties.cb_encountered_error = true;
|
||||
}
|
||||
#define IMG4UNTAG(x) (((x) >> 24) & 0xff),(((x) >> 16) & 0xff),(((x) >> 8) & 0xff),((x) & 0xff)
|
||||
|
||||
static int image4_copy_boolean_properties(DTNode* node, bool_prop_t* props)
|
||||
{
|
||||
char entryName[50];
|
||||
char* propName;
|
||||
void* propData;
|
||||
uint32_t propSize;
|
||||
for(int i = 0; (i < N_BOOL_PROPS) && (props[i].tag != 0); i++) {
|
||||
snprintf(entryName, sizeof(entryName), "UnusedBooleanProperty%d", i);
|
||||
propName = entryName;
|
||||
if (!FindProperty(node, &propName, &propData, &propSize)) {
|
||||
dprintf(DEBUG_CRITICAL, "Ran out of boolean entries %s", propName);
|
||||
return -1;
|
||||
}
|
||||
snprintf(entryName, sizeof(entryName), "%c%c%c%c", IMG4UNTAG(props[i].tag));
|
||||
strlcpy(propName, entryName, kPropNameLength);
|
||||
memcpy(propData, &props[i].val, sizeof(bool));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int image4_copy_integer_properties(DTNode* node, int_prop_t* props)
|
||||
{
|
||||
char entryName[50];
|
||||
char* propName;
|
||||
void* propData;
|
||||
uint32_t propSize;
|
||||
for(int i = 0; (i < N_INT_PROPS) && (props[i].tag != 0); i++) {
|
||||
snprintf(entryName, sizeof(entryName), "UnusedIntegerProperty%d", i);
|
||||
propName = entryName;
|
||||
if (!FindProperty(node, &propName, &propData, &propSize)) {
|
||||
dprintf(DEBUG_CRITICAL, "Ran out of integer entries %s", propName);
|
||||
return -1;
|
||||
}
|
||||
snprintf(entryName, sizeof(entryName), "%c%c%c%c", IMG4UNTAG(props[i].tag));
|
||||
strlcpy(propName, entryName, kPropNameLength);
|
||||
memcpy(propData, &props[i].val, sizeof(uint64_t));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int image4_copy_string_properties(DTNode* node, string_prop_t* props)
|
||||
{
|
||||
char entryName[50];
|
||||
char* propName;
|
||||
void* propData;
|
||||
uint32_t propSize;
|
||||
for(int i = 0; (i < N_STRING_PROPS) && (props[i].tag != 0); i++) {
|
||||
snprintf(entryName, sizeof(entryName), "UnusedStringProperty%d", i);
|
||||
propName = entryName;
|
||||
if (!FindProperty(node, &propName, &propData, &propSize)) {
|
||||
dprintf(DEBUG_CRITICAL, "Ran out of string entries %s", propName);
|
||||
return -1;
|
||||
}
|
||||
if (propSize < props[i].length) {
|
||||
dprintf(DEBUG_CRITICAL, "DT property size too small to fit string property");
|
||||
return -2;
|
||||
}
|
||||
|
||||
snprintf(entryName, sizeof(entryName), "%c%c%c%c", IMG4UNTAG(props[i].tag));
|
||||
strlcpy(propName, entryName, kPropNameLength);
|
||||
memcpy(propData, &props[i].data, props[i].length);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool initialized;
|
||||
|
||||
int target_init_boot_manifest(void)
|
||||
{
|
||||
image4_register_property_capture_callbacks(image4_start_cb,
|
||||
image4_bool_cb, image4_int_cb, image4_string_cb, image4_update_validity);
|
||||
initialized=true;
|
||||
return 0;
|
||||
}
|
||||
int target_pass_boot_manifest(void)
|
||||
{
|
||||
// You must call init before loading the image4 of interest.
|
||||
if (!initialized)
|
||||
panic("target_pass_boot_manifest() used without target_init_boot_manifest()");
|
||||
|
||||
if (!image4_properties.is_valid || image4_properties.cb_encountered_error) {
|
||||
// Don't touch the DT unless the image is validated.
|
||||
return -1;
|
||||
}
|
||||
const char* ManifestPropertiesPath = "chosen/manifest-properties";
|
||||
const char* ManifestObjectPropertiesPath = "chosen/manifest-object-properties";
|
||||
DTNode* dtnode;
|
||||
if (FindNode(0, ManifestPropertiesPath, &dtnode)) {
|
||||
if (image4_copy_boolean_properties(dtnode, image4_properties.manifest_properties.bool_props))
|
||||
return -2;
|
||||
|
||||
if (image4_copy_integer_properties(dtnode, image4_properties.manifest_properties.int_props))
|
||||
return -3;
|
||||
|
||||
if (image4_copy_string_properties(dtnode, image4_properties.manifest_properties.string_props))
|
||||
return -4;
|
||||
} else {
|
||||
dprintf(DEBUG_CRITICAL, "Can't find manifest properties path %s -- Skipping DT patching\n", ManifestPropertiesPath);
|
||||
return -5;
|
||||
}
|
||||
if (FindNode(0, ManifestObjectPropertiesPath, &dtnode)) {
|
||||
if (image4_copy_boolean_properties(dtnode, image4_properties.manifest_object_properties.bool_props))
|
||||
return -6;
|
||||
if (image4_copy_integer_properties(dtnode, image4_properties.manifest_object_properties.int_props))
|
||||
return -7;
|
||||
if (image4_copy_string_properties(dtnode, image4_properties.manifest_object_properties.string_props))
|
||||
return -8;
|
||||
} else {
|
||||
dprintf(DEBUG_CRITICAL, "Can't find manifest object properties path %s -- Skipping DT patching\n", ManifestObjectPropertiesPath);
|
||||
return -9;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user