first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (C) 2012-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.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <arch/arm/arm.h>
|
||||
#include <drivers/dart.h>
|
||||
#include <platform/soc/hwregbase.h>
|
||||
#include <sys.h>
|
||||
#include "dart_regs.h"
|
||||
|
||||
#if DART_PAGE_SIZE != DART_TT_PGSIZE
|
||||
#error "The generic header's idea of the page size doesn't agree with this driver"
|
||||
#endif
|
||||
|
||||
typedef uint64_t dart_ent;
|
||||
|
||||
typedef struct dart_l2_tt {
|
||||
dart_ent *tt_base;
|
||||
uintptr_t tt_phys;
|
||||
|
||||
dart_ent *l3_tt_bases[DART_TTE_PGENTRIES];
|
||||
} dart_l2_tt_t;
|
||||
|
||||
typedef struct dart {
|
||||
uintptr_t regs;
|
||||
dart_l2_tt_t *l2_tts[DART_NUM_TTBR];
|
||||
dart_iovm_addr_t addr_mask;
|
||||
} dart_t;
|
||||
|
||||
dart_t darts[NUM_DARTS];
|
||||
|
||||
static void *alloc_tt_page(void)
|
||||
{
|
||||
void *result;
|
||||
result = memalign(DART_TT_PGSIZE, DART_TT_PGSIZE);
|
||||
bzero(result, DART_TT_PGSIZE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void flush_tlb(dart_t *dart)
|
||||
{
|
||||
arm_memory_barrier();
|
||||
|
||||
// Flush SID 0
|
||||
rDART_TLB_OP(dart->regs) = DART_TLB_OP_FLUSH | DART_TLB_OP_SID_MASK0;
|
||||
|
||||
while(rDART_TLB_OP(dart->regs) & DART_TLB_OP_BUSY)
|
||||
;
|
||||
}
|
||||
|
||||
// Clear out any L3 entries in the DART so that nothing is mapped into IO virtual
|
||||
// space. Don't clear out the mappings at the L2 level, just at L3. The DART
|
||||
// doesn't support block mappings, so L2 entries can never cause a mapping
|
||||
// without a subsequent L3 entry.
|
||||
static void clear_mappings(dart_t *dart)
|
||||
{
|
||||
unsigned int i, j;
|
||||
dart_l2_tt_t *l2_tt;
|
||||
dart_ent *l3_tt_base;
|
||||
|
||||
for (i = 0; i < DART_NUM_TTBR; i++) {
|
||||
|
||||
l2_tt = dart->l2_tts[i];
|
||||
if (l2_tt == NULL)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < DART_TTE_PGENTRIES; j++) {
|
||||
l3_tt_base = l2_tt->l3_tt_bases[j];
|
||||
|
||||
if (l3_tt_base != NULL)
|
||||
memset(l3_tt_base, 0, DART_TT_PGSIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dart_init(unsigned int dart_id)
|
||||
{
|
||||
dart_t *dart;
|
||||
uint32_t reg;
|
||||
|
||||
ASSERT(dart_id < NUM_DARTS);
|
||||
dart = &darts[dart_id];
|
||||
|
||||
switch (dart_id)
|
||||
{
|
||||
#ifdef DART0_BASE_ADDR
|
||||
case 0:
|
||||
dart->regs = DART0_BASE_ADDR;
|
||||
dart->addr_mask = DART0_ADDR_MASK;
|
||||
break;
|
||||
#endif
|
||||
#ifdef DART1_BASE_ADDR
|
||||
case 1:
|
||||
dart->regs = DART1_BASE_ADDR;
|
||||
dart->addr_mask = DART1_ADDR_MASK;
|
||||
break;
|
||||
#endif
|
||||
#ifdef DART2_BASE_ADDR
|
||||
case 2:
|
||||
dart->regs = DART2_BASE_ADDR;
|
||||
dart->addr_mask = DART2_ADDR_MASK;
|
||||
break;
|
||||
#endif
|
||||
#ifdef DART3_BASE_ADDR
|
||||
case 3:
|
||||
dart->regs = DART3_BASE_ADDR;
|
||||
dart->addr_mask = DART3_ADDR_MASK;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Unknown DART index %d", dart_id);
|
||||
break;
|
||||
}
|
||||
|
||||
// If the DART has previously been initialized, we need to clear out all mappings
|
||||
// This will be a quick no-op if the DART hasn't been initialized
|
||||
clear_mappings(dart);
|
||||
|
||||
// If for some reason translation gets disabled, bypass to an invalid
|
||||
// address instead of DRAM
|
||||
rDART_BYPASS_ADDR(dart->regs) = 0;
|
||||
|
||||
rDART_DIAG_BOGUS_ACCESS(dart->regs) = ERR_REFLECTION_BASE_ADDR >> 12;
|
||||
|
||||
// Tunables
|
||||
rDART_DIAG_CONFIG(dart->regs) |= DART_DIAG_CONFIG_PTE_FETCH_PROMOTE_QOS;
|
||||
reg = rDART_FETCH_REQ_CONFIG(dart->regs);
|
||||
reg &= ~DART_FETCH_REQ_CONFIG_STE(0xf);
|
||||
reg |= DART_FETCH_REQ_CONFIG_STE(0x3);
|
||||
reg &= ~DART_FETCH_REQ_CONFIG_PTE(0xf);
|
||||
reg |= DART_FETCH_REQ_CONFIG_PTE(0x3);
|
||||
reg &= ~DART_FETCH_REQ_CONFIG_PTE_PREFETCH(0xf);
|
||||
reg |= DART_FETCH_REQ_CONFIG_PTE_PREFETCH(0xe);
|
||||
rDART_FETCH_REQ_CONFIG(dart->regs) = reg;
|
||||
|
||||
// Restore TTBRs if we were previously enabled, otherwise initialize
|
||||
// all the TTBRs to 0
|
||||
dart_enable_translation(dart_id);
|
||||
|
||||
// Enable translation and exceptions for SID 0
|
||||
rDART_CONFIG(dart->regs) = 0x80;
|
||||
}
|
||||
|
||||
/* Disables all TTBRs and flushes the TLB, but leaves translation enabled. This will
|
||||
* make sure that all translation attempts result in an error. If we disabled translation,
|
||||
* all translation attempts would go to the bypass address, which is not what we want */
|
||||
void dart_disable_translation(unsigned int dart_id)
|
||||
{
|
||||
dart_t *dart;
|
||||
int i;
|
||||
|
||||
ASSERT(dart_id < NUM_DARTS);
|
||||
dart = &darts[dart_id];
|
||||
|
||||
for (i = 0; i < DART_NUM_TTBR; i++)
|
||||
rDART_TTBR(dart->regs, i) = 0;
|
||||
|
||||
flush_tlb(dart);
|
||||
}
|
||||
|
||||
/* Re-enables mappings that were previously created with dart_map_page_range by reprogramming
|
||||
* the DART's TTBRs with the previously created translation tables */
|
||||
void dart_enable_translation(unsigned int dart_id)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t ttbr;
|
||||
dart_t *dart;
|
||||
dart_l2_tt_t *l2_tt;
|
||||
|
||||
ASSERT(dart_id < NUM_DARTS);
|
||||
dart = &darts[dart_id];
|
||||
|
||||
for (i = 0; i < DART_NUM_TTBR; i++) {
|
||||
l2_tt = dart->l2_tts[i];
|
||||
|
||||
if (l2_tt == NULL) {
|
||||
ttbr = 0;
|
||||
} else {
|
||||
ttbr = (l2_tt->tt_phys >> DART_TTBR_SHIFT) | DART_TTBR_VALID;
|
||||
}
|
||||
|
||||
rDART_TTBR(dart->regs, i) = ttbr;
|
||||
}
|
||||
|
||||
flush_tlb(dart);
|
||||
}
|
||||
|
||||
void dart_map_page_range(unsigned int dart_id, uintptr_t paddr, dart_iovm_addr_t vaddr, uint32_t pages, bool write_protect)
|
||||
{
|
||||
uint32_t ttbr;
|
||||
uint32_t i;
|
||||
dart_iovm_addr_t page_vaddr;
|
||||
uintptr_t page_paddr;
|
||||
dart_ent ent;
|
||||
dart_t *dart;
|
||||
|
||||
ASSERT(dart_id < NUM_DARTS);
|
||||
dart = &darts[dart_id];
|
||||
|
||||
ASSERT((vaddr & DART_TT_L3_OFFMASK) == 0);
|
||||
ASSERT((paddr & DART_TT_L3_OFFMASK) == 0);
|
||||
|
||||
page_vaddr = vaddr & dart->addr_mask;
|
||||
page_paddr = paddr;
|
||||
|
||||
dprintf(DEBUG_SPEW, "dart%d: mapped 0x%04x pages at iovm 0x%08x to phys %p\n", dart_id, pages, vaddr, (void *)paddr);
|
||||
|
||||
for (i = 0; i < pages; i++) {
|
||||
uint32_t l1_index = (page_vaddr & DART_TT_L1_INDEX_MASK) >> DART_TT_L1_SHIFT;
|
||||
uint32_t l2_index = (page_vaddr & DART_TT_L2_INDEX_MASK) >> DART_TT_L2_SHIFT;
|
||||
uint32_t l3_index = (page_vaddr & DART_TT_L3_INDEX_MASK) >> DART_TT_L3_SHIFT;
|
||||
dart_l2_tt_t *l2_tt;
|
||||
dart_ent *l3_tt;
|
||||
|
||||
if (dart->l2_tts[l1_index] == NULL) {
|
||||
dart_ent *new_tt;
|
||||
uintptr_t new_tt_phys;
|
||||
|
||||
new_tt = alloc_tt_page();
|
||||
new_tt_phys = mem_static_map_physical((uintptr_t)new_tt);
|
||||
dart->l2_tts[l1_index] = calloc(1, sizeof(dart_l2_tt_t));
|
||||
dart->l2_tts[l1_index]->tt_base = new_tt;
|
||||
dart->l2_tts[l1_index]->tt_phys = new_tt_phys;
|
||||
|
||||
ttbr = (new_tt_phys >> DART_TTBR_SHIFT) | DART_TTBR_VALID;
|
||||
rDART_TTBR(dart->regs, l1_index) = ttbr;
|
||||
}
|
||||
l2_tt = dart->l2_tts[l1_index];
|
||||
|
||||
if (l2_tt->l3_tt_bases[l2_index] == NULL) {
|
||||
dart_ent *new_tt = alloc_tt_page();
|
||||
l2_tt->l3_tt_bases[l2_index] = new_tt;
|
||||
|
||||
ent = ((uintptr_t)mem_static_map_physical((uintptr_t)new_tt)) | DART_TTE_TABLE | DART_TTE_VALID;
|
||||
l2_tt->tt_base[l2_index] = ent;
|
||||
}
|
||||
l3_tt = l2_tt->l3_tt_bases[l2_index];
|
||||
|
||||
RELEASE_ASSERT(l3_tt[l3_index] == 0);
|
||||
|
||||
ent = page_paddr | DART_PTE_WRPROT(write_protect) | DART_PTE_TYPE_VALID;
|
||||
l3_tt[l3_index] = ent;
|
||||
|
||||
page_vaddr += DART_TT_L3_SIZE;
|
||||
page_paddr += DART_TT_L3_SIZE;
|
||||
}
|
||||
|
||||
flush_tlb(dart);
|
||||
}
|
||||
|
||||
void dart_unmap_page_range(unsigned int dart_id, dart_iovm_addr_t vaddr, uint32_t pages)
|
||||
{
|
||||
uint32_t i;
|
||||
dart_iovm_addr_t page_vaddr;
|
||||
dart_t *dart;
|
||||
|
||||
ASSERT(dart_id < NUM_DARTS);
|
||||
dart = &darts[dart_id];
|
||||
|
||||
ASSERT((vaddr & DART_TT_L3_OFFMASK) == 0);
|
||||
|
||||
dprintf(DEBUG_SPEW, "dart%d: unmapped 0x%04x pages at iovm 0x%08x\n", dart_id, pages, vaddr);
|
||||
|
||||
page_vaddr = vaddr & dart->addr_mask;
|
||||
|
||||
for (i = 0; i < pages; i++) {
|
||||
uint32_t l1_index = (page_vaddr & DART_TT_L1_INDEX_MASK) >> DART_TT_L1_SHIFT;
|
||||
uint32_t l2_index = (page_vaddr & DART_TT_L2_INDEX_MASK) >> DART_TT_L2_SHIFT;
|
||||
uint32_t l3_index = (page_vaddr & DART_TT_L3_INDEX_MASK) >> DART_TT_L3_SHIFT;
|
||||
dart_l2_tt_t *l2_tt;
|
||||
dart_ent *l3_tt;
|
||||
|
||||
l2_tt = dart->l2_tts[l1_index];
|
||||
RELEASE_ASSERT(l2_tt != NULL);
|
||||
|
||||
l3_tt = l2_tt->l3_tt_bases[l2_index];
|
||||
RELEASE_ASSERT(l3_tt != NULL);
|
||||
|
||||
l3_tt[l3_index] = 0;
|
||||
|
||||
page_vaddr += DART_TT_L3_SIZE;
|
||||
}
|
||||
|
||||
flush_tlb(dart);
|
||||
}
|
||||
|
||||
void dart_write_protect_page_range(unsigned int dart_id, dart_iovm_addr_t vaddr, uint32_t pages, bool write_protect)
|
||||
{
|
||||
uint32_t i;
|
||||
dart_iovm_addr_t page_vaddr;
|
||||
dart_ent ent;
|
||||
dart_t *dart;
|
||||
|
||||
ASSERT(dart_id < NUM_DARTS);
|
||||
dart = &darts[dart_id];
|
||||
|
||||
ASSERT((vaddr & DART_TT_L3_OFFMASK) == 0);
|
||||
|
||||
page_vaddr = vaddr;
|
||||
|
||||
for (i = 0; i < pages; i++) {
|
||||
uint32_t l1_index = (page_vaddr & DART_TT_L1_INDEX_MASK) >> DART_TT_L1_SHIFT;
|
||||
uint32_t l2_index = (page_vaddr & DART_TT_L2_INDEX_MASK) >> DART_TT_L2_SHIFT;
|
||||
uint32_t l3_index = (page_vaddr & DART_TT_L3_INDEX_MASK) >> DART_TT_L3_SHIFT;
|
||||
dart_l2_tt_t *l2_tt;
|
||||
dart_ent *l3_tt;
|
||||
|
||||
l2_tt = dart->l2_tts[l1_index];
|
||||
RELEASE_ASSERT(l2_tt != NULL);
|
||||
|
||||
l3_tt = l2_tt->l3_tt_bases[l2_index];
|
||||
RELEASE_ASSERT(l3_tt != NULL);
|
||||
|
||||
ent = l3_tt[l3_index];
|
||||
ent &= DART_PTE_PAGE_MASK;
|
||||
ent |= DART_PTE_WRPROT(write_protect);
|
||||
l3_tt[l3_index] = ent;
|
||||
|
||||
page_vaddr += DART_TT_L3_SIZE;
|
||||
}
|
||||
|
||||
flush_tlb(dart);
|
||||
}
|
||||
|
||||
// Verifies that all mappings have been removed from the DART. This is used
|
||||
// to verify that drivers aren't leaking mappings, as leaked mappings could
|
||||
// lead to a security hole
|
||||
void dart_assert_unmapped(unsigned int dart_id)
|
||||
{
|
||||
dart_t *dart;
|
||||
unsigned int i, j, k;
|
||||
dart_l2_tt_t *l2_tt;
|
||||
dart_ent *l3_tt_base;
|
||||
|
||||
ASSERT(dart_id < NUM_DARTS);
|
||||
dart = &darts[dart_id];
|
||||
|
||||
for (i = 0; i < DART_NUM_TTBR; i++) {
|
||||
// If the driver isn't tracking an L2 table under the given TTBR,
|
||||
// then, the TTBR needs to be 0
|
||||
l2_tt = dart->l2_tts[i];
|
||||
if (l2_tt == NULL) {
|
||||
RELEASE_ASSERT(rDART_TTBR(dart->regs, i) == 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
// For each L2 table, verify each entry is either 0 or points
|
||||
// to an L3 table filled with 0s
|
||||
for (j = 0; j < DART_TTE_PGENTRIES; j++) {
|
||||
l3_tt_base = l2_tt->l3_tt_bases[j];
|
||||
|
||||
if (l3_tt_base != NULL) {
|
||||
for (k = 0; k < DART_TTE_PGENTRIES; k++) {
|
||||
RELEASE_ASSERT(l3_tt_base[k] == 0);
|
||||
}
|
||||
} else {
|
||||
RELEASE_ASSERT(l2_tt->tt_base[j] == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.
|
||||
*/
|
||||
#ifndef DART_REGS_H
|
||||
#define DART_REGS_H
|
||||
|
||||
#define DART_TT_PGSIZE 4096
|
||||
#define DART_TTE_SHIFT 3
|
||||
#define DART_TTE_PGENTRIES (DART_TT_PGSIZE >> DART_TTE_SHIFT)
|
||||
|
||||
#define DART_TTE_VALID (1 << 0)
|
||||
#define DART_TTE_TABLE (1 << 1)
|
||||
|
||||
#define DART_NUM_TTBR 4
|
||||
#define DART_NUM_SID 4
|
||||
|
||||
#define rDART_TLB_OP(base) (*(volatile uint32_t *)((base) + 0x00))
|
||||
#define rDART_CONFIG(base) (*(volatile uint32_t *)((base) + 0x0c))
|
||||
#define rDART_DIAG_CONFIG(base) (*(volatile uint32_t *)((base) + 0x20))
|
||||
#define rDART_DIAG_BOGUS_ACCESS(base) (*(volatile uint32_t *)((base) + 0x24))
|
||||
#define rDART_BYPASS_ADDR(base) (*(volatile uint32_t *)((base) + 0x2c))
|
||||
#define rDART_FETCH_REQ_CONFIG(base) (*(volatile uint32_t *)((base) + 0x30))
|
||||
#define rDART_TTBR(base, idx) (*(volatile uint32_t *)((base) + 0x40 + 4 * (idx)))
|
||||
|
||||
#define DART_TLB_OP_FLUSH (2)
|
||||
#define DART_TLB_OP_BUSY (1 << 3)
|
||||
#define DART_TLB_OP_SID_MASK0 (1 << 8)
|
||||
#define DART_TLB_OP_SID_MASK1 (1 << 9)
|
||||
#define DART_TLB_OP_SID_MASK2 (1 << 10)
|
||||
#define DART_TLB_OP_SID_MASK3 (1 << 11)
|
||||
|
||||
#define DART_DIAG_CONFIG_PTE_FETCH_PROMOTE_QOS (1 << 8)
|
||||
|
||||
#define DART_FETCH_REQ_CONFIG_STE(x) (((x) & 0xf) << 0)
|
||||
#define DART_FETCH_REQ_CONFIG_PTE(x) (((x) & 0xf) << 8)
|
||||
#define DART_FETCH_REQ_CONFIG_PTE_PREFETCH(x) (((x) & 0xf) << 16)
|
||||
|
||||
#define DART_TTBR_VALID (1 << 31)
|
||||
#define DART_TTBR_SHIFT (12)
|
||||
|
||||
/*
|
||||
* L1 Translation table (stored in registers)
|
||||
*
|
||||
* There are DART_NUM_TTBR entries in the L1 table
|
||||
* DART_NUM_TTBR entries of 1GB (2^30) of address space.
|
||||
*/
|
||||
#define DART_TT_L1_SIZE 0x0000000040000000ULL /* size of area covered by a tte */
|
||||
#define DART_TT_L1_OFFMASK 0x000000003fffffffULL /* offset within an L2 entry */
|
||||
#define DART_TT_L1_SHIFT 30
|
||||
#define DART_TT_L1_INDEX_MASK 0x0000000070000000ULL /* mask for getting index in L1 table from virtual address */
|
||||
|
||||
/*
|
||||
* L2 Translation table
|
||||
*
|
||||
* Each translation table is 4KB
|
||||
* 512 64-bit entries of 2MB (2^21) of address space.
|
||||
*/
|
||||
|
||||
#define DART_TT_L2_SIZE 0x0000000000200000ULL /* size of area covered by a tte */
|
||||
#define DART_TT_L2_OFFMASK 0x00000000001fffffULL /* offset within an L2 entry */
|
||||
#define DART_TT_L2_SHIFT 21 /* page descriptor shift */
|
||||
#define DART_TT_L2_INDEX_MASK 0x000000003fe00000ULL /* mask for getting index in L2 table from virtual address */
|
||||
|
||||
/*
|
||||
* L3 Translation table
|
||||
*
|
||||
* Each translation table is 4KB
|
||||
* 512 64-bit entries of 4KB (2^12) of address space.
|
||||
*/
|
||||
|
||||
#define DART_TT_L3_SIZE 0x0000000000001000ULL /* size of area covered by a tte */
|
||||
#define DART_TT_L3_OFFMASK 0x0000000000000fffULL /* offset within L3 PTE */
|
||||
#define DART_TT_L3_SHIFT 12 /* page descriptor shift */
|
||||
#define DART_TT_L3_INDEX_MASK 0x00000000001ff000ULL /* mask for page descriptor index */
|
||||
|
||||
/*
|
||||
* L3 Page table entries
|
||||
*
|
||||
* The following page table entry types are possible:
|
||||
*
|
||||
* fault page entry
|
||||
* 63 2 0
|
||||
* +------------------------------+--+
|
||||
* | ignored |00|
|
||||
* +------------------------------+--+
|
||||
*
|
||||
*
|
||||
* 63 52 51 36 35 12 11 8 7 6 2 1 0
|
||||
* +-----+------+----------------------+-----+-+-----+-+-+
|
||||
* | ign | zero | OutputAddress[35:12] | ign |W| ign |1|V|
|
||||
* +-----+------+----------------------+-----+-+-----+-+-+
|
||||
*
|
||||
* where:
|
||||
* 'W' Write orotect bit
|
||||
* 'V' Valid bit
|
||||
*/
|
||||
|
||||
#define DART_PTE_SHIFT 3
|
||||
#define DART_PTE_PGENTRIES (DART_TT_PGSIZE >> DART_PTE_SHIFT)
|
||||
|
||||
#define DART_PTE_EMPTY 0x0000000000000000ULL /* unasigned - invalid entry */
|
||||
|
||||
#define DART_PTE_TYPE_VALID 0x0000000000000003ULL /* valid L3 entry: includes bit #1 (counterintuitively) */
|
||||
|
||||
#define DART_PTE_PAGE_MASK 0x0000FFFFFFFFF000ULL /* mask for 4KB page */
|
||||
#define DART_PTE_PAGE_SHIFT 12 /* page shift for 4KB page */
|
||||
|
||||
#define DART_PTE_WRPROT(enable) ((enable) ? (1 << 7) : 0) /* write protect */
|
||||
|
||||
#endif // DART_REGS_H
|
||||
@@ -0,0 +1,16 @@
|
||||
# Copyright (C) 2012 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)
|
||||
|
||||
OPTIONS += \
|
||||
WITH_HW_DART=1
|
||||
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/dart.o
|
||||
Reference in new issue
Block a user