aboutsummaryrefslogtreecommitdiffstats
path: root/tools/firmware/acpi/acpi_build.c
blob: f947d2707d54ae83ec4a3701b0ff4b686b191707 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*
 * Copyright (c) 2004, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307 USA.
 *
 */

#include "acpi2_0.h"
#include "acpi_madt.h"

extern ACPI_2_0_RSDP Rsdp;
extern ACPI_2_0_RSDT Rsdt;
extern ACPI_2_0_XSDT Xsdt;
extern ACPI_2_0_FADT Fadt;
extern ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE Madt;
extern ACPI_2_0_FACS Facs;
extern unsigned char *AmlCode;
extern int DsdtLen;


typedef struct _ACPI_TABLE_ALL{
		ACPI_2_0_RSDP *Rsdp;
		ACPI_2_0_RSDT *Rsdt;
		ACPI_2_0_XSDT *Xsdt;
		ACPI_2_0_FADT *Fadt;
		ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *Madt;
		ACPI_2_0_FACS *Facs;
		unsigned char* Dsdt;
		u32 RsdpOffset;
		u32 RsdtOffset;
		u32 XsdtOffset;
		u32 FadtOffset;
		u32 MadtOffset;
		u32 FacsOffset;
		u32 DsdtOffset;
}ACPI_TABLE_ALL;

static 
void
MemCopy(void* src, void* dst, int len){

	u8* src0=src;
   	u8* dst0=dst;	

	while(len--){
		*(dst0++)=*(src0++);
	}
}

static
void
SetCheckSum(
  void*  Table, 
  u32 ChecksumOffset,
  u32 Length
)
/*
 * Routine Description:
 *      Calculate Checksum and store the result in the checksum 
 * 	filed of the table	
 *
 * INPUT:
 * 	Table:          Start pointer of table
 * 	ChecksumOffset: Offset of checksum field in the table
 * 	Length:         Length of Table
 */
{
	u8 Sum = 0;  
	u8 *Ptr;

	Ptr=Table;
	Ptr[ChecksumOffset]=0;
	while (Length--) {    
		Sum = (u8)(Sum + (*Ptr++));
	}
	
	Ptr = Table;
	Ptr[ChecksumOffset] = (u8) (0xff - Sum + 1);
}

//
//  FIELD_OFFSET - returns the byte offset to a field within a structure
//
#define FIELD_OFFSET(TYPE,Field) ((u32)(&(((TYPE *) 0)->Field)))

static
void
UpdateTable(
	ACPI_TABLE_ALL *table
)
/*
 * Update the ACPI table:
 * 		fill in the actuall physical address of RSDT, XSDT, FADT, MADT, FACS
 * 		Caculate the checksum
 */
{    
	// RSDP Update	
	table->Rsdp->RsdtAddress = (u32)(ACPI_PHYSICAL_ADDRESS+
					table->RsdtOffset);
	table->Rsdp->XsdtAddress = (u64)(ACPI_PHYSICAL_ADDRESS+
					table->XsdtOffset);
	SetCheckSum(table->Rsdp,
					FIELD_OFFSET(ACPI_1_0_RSDP, Checksum),
					sizeof(ACPI_1_0_RSDP)
			   );
	SetCheckSum(table->Rsdp,
					FIELD_OFFSET(ACPI_2_0_RSDP,
							ExtendedChecksum),
					sizeof(ACPI_2_0_RSDP)
			   );

	
	//RSDT Update
	table->Rsdt->Entry[0] = (u32)(ACPI_PHYSICAL_ADDRESS + 
					table->FadtOffset);	
	table->Rsdt->Entry[1] = (u32)(ACPI_PHYSICAL_ADDRESS + 
					table->MadtOffset);
	table->Rsdt->Header.Length = sizeof (ACPI_TABLE_HEADER) +
		   			2*sizeof(u32);
	SetCheckSum(table->Rsdt,
					FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum),
					table->Rsdt->Header.Length
			   );	
	
	//XSDT	Update
	table->Xsdt->Entry[0] = (u64)(ACPI_PHYSICAL_ADDRESS +
					table->FadtOffset);
	table->Xsdt->Entry[1] = (u64)(ACPI_PHYSICAL_ADDRESS + 
					table->MadtOffset);	
	table->Xsdt->Header.Length = sizeof (ACPI_TABLE_HEADER) + 
					2*sizeof(u64);
	SetCheckSum(table->Xsdt,
					FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum),
					table->Xsdt->Header.Length
			   );

	// FADT Update
	table->Fadt->Dsdt = (u32)(ACPI_PHYSICAL_ADDRESS + 
					table->DsdtOffset);	
	table->Fadt->XDsdt = (u64)(ACPI_PHYSICAL_ADDRESS + 
				   table->DsdtOffset);
	table->Fadt->FirmwareCtrl = (u32)(ACPI_PHYSICAL_ADDRESS +
					table->FacsOffset);
	table->Fadt->XFirmwareCtrl = (u64)(ACPI_PHYSICAL_ADDRESS + 
					table->FacsOffset);	
	SetCheckSum(table->Fadt,
					FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum),
					sizeof(ACPI_2_0_FADT)
			   );
	
	// MADT update
	SetCheckSum(table->Madt,
					FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum),
					sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE)
			   );
}

void
AcpiBuildTable(u8* buf)
/*
 * Copy all the ACPI table to buffer
 * Buffer Layout:
 * 		FACS
 * 		RSDP
 * 		RSDT
 * 		XSDT
 * 		FADT
 * 		MADT
 * 		DSDT 		
 *
 */		
{
	ACPI_TABLE_ALL table;
	int offset=0;

	// FACS: should be 64-bit alignment 	
	// so it is put at the start of buffer
	// as the buffer is 64 bit alignment
	table.FacsOffset = offset;
	table.Facs = (ACPI_2_0_FACS*)(&buf[offset]);
	MemCopy(&Facs, table.Facs, sizeof(ACPI_2_0_FACS));
	offset += sizeof(ACPI_2_0_FACS);

	// RSDP
	table.RsdpOffset = offset;
	table.Rsdp = (ACPI_2_0_RSDP*)(&buf[offset]);
	MemCopy(&Rsdp, table.Rsdp, sizeof(ACPI_2_0_RSDP));
	offset+=sizeof(ACPI_2_0_RSDP);

	// RSDT
	table.RsdtOffset = offset;
	table.Rsdt = (ACPI_2_0_RSDT*)(&buf[offset]);
	MemCopy(&Rsdt, table.Rsdt, sizeof(ACPI_2_0_RSDT));
	offset+=sizeof(ACPI_2_0_RSDT);
	
	// XSDT
	table.XsdtOffset = offset;
	table.Xsdt = (ACPI_2_0_XSDT*)(&buf[offset]);
	MemCopy(&Xsdt, table.Xsdt, sizeof(ACPI_2_0_XSDT));
	offset+=sizeof(ACPI_2_0_XSDT);
	
	// FADT
	table.FadtOffset = offset;
	table.Fadt = (ACPI_2_0_FADT*)(&buf[offset]);
	MemCopy(&Fadt, table.Fadt, sizeof(ACPI_2_0_FADT));
	offset+=sizeof(ACPI_2_0_FADT);
	
	// MADT
	table.MadtOffset = offset;
	table.Madt = (ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE*)(&buf[offset]);
	MemCopy(&Madt, table.Madt, sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE));
	offset+=sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE);

	// DSDT
	table.DsdtOffset = offset;
	table.Dsdt = (unsigned char*)(&buf[offset]);
	MemCopy(&AmlCode, table.Dsdt, DsdtLen);
	offset+=DsdtLen; 
	
	UpdateTable(&table);
}