blob: c370321835f61cde5b183544f05e5f7e13bbf804 [file] [log] [blame]
Rudolf Marek293b5f52009-02-01 18:35:15 +00001/*
2 * This file is part of the coreboot project.
3 *
Timothy Pearson83abd812015-06-08 19:35:06 -05004 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Rudolf Marek293b5f52009-02-01 18:35:15 +00005 * Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz>
6 *
7 * This program is free software; you can redistribute it and/or modify
Uwe Hermannc70e9fc2010-02-15 23:10:19 +00008 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
Rudolf Marek293b5f52009-02-01 18:35:15 +000010 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Rudolf Marek293b5f52009-02-01 18:35:15 +000015 */
16
Paul Menzel0f4c0e22013-02-22 12:33:08 +010017/* How much nesting do we support? */
Rudolf Marek293b5f52009-02-01 18:35:15 +000018#define ACPIGEN_LENSTACK_SIZE 10
19
Paul Menzel0f4c0e22013-02-22 12:33:08 +010020/*
Timothy Pearson83abd812015-06-08 19:35:06 -050021 * If you need to change this, change acpigen_write_len_f and
Vladimir Serbinenko8104da72014-11-09 03:33:51 +010022 * acpigen_pop_len
Paul Menzel0f4c0e22013-02-22 12:33:08 +010023 */
Rudolf Marek293b5f52009-02-01 18:35:15 +000024
Timothy Pearson83abd812015-06-08 19:35:06 -050025#define ACPIGEN_MAXLEN 0xfffff
Rudolf Marek293b5f52009-02-01 18:35:15 +000026
Duncan Laurie3829f232016-05-09 11:08:46 -070027#include <lib.h>
Rudolf Marek293b5f52009-02-01 18:35:15 +000028#include <string.h>
29#include <arch/acpigen.h>
30#include <console/console.h>
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +000031#include <device/device.h>
Rudolf Marek293b5f52009-02-01 18:35:15 +000032
33static char *gencurrent;
34
35char *len_stack[ACPIGEN_LENSTACK_SIZE];
36int ltop = 0;
37
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +010038void acpigen_write_len_f(void)
Rudolf Marek293b5f52009-02-01 18:35:15 +000039{
40 ASSERT(ltop < (ACPIGEN_LENSTACK_SIZE - 1))
Paul Menzel0f4c0e22013-02-22 12:33:08 +010041 len_stack[ltop++] = gencurrent;
Rudolf Marek293b5f52009-02-01 18:35:15 +000042 acpigen_emit_byte(0);
43 acpigen_emit_byte(0);
Timothy Pearson83abd812015-06-08 19:35:06 -050044 acpigen_emit_byte(0);
Rudolf Marek293b5f52009-02-01 18:35:15 +000045}
46
Vladimir Serbinenko430363a2014-11-02 21:51:22 +010047void acpigen_pop_len(void)
48{
49 int len;
50 ASSERT(ltop > 0)
51 char *p = len_stack[--ltop];
52 len = gencurrent - p;
53 ASSERT(len <= ACPIGEN_MAXLEN)
Timothy Pearson83abd812015-06-08 19:35:06 -050054 /* generate store length for 0xfffff max */
55 p[0] = (0x80 | (len & 0xf));
Vladimir Serbinenko430363a2014-11-02 21:51:22 +010056 p[1] = (len >> 4 & 0xff);
Timothy Pearson83abd812015-06-08 19:35:06 -050057 p[2] = (len >> 12 & 0xff);
Vladimir Serbinenko430363a2014-11-02 21:51:22 +010058
59}
60
Stefan Reinauerf96c2d92009-04-22 16:23:47 +000061void acpigen_set_current(char *curr)
62{
63 gencurrent = curr;
Rudolf Marek293b5f52009-02-01 18:35:15 +000064}
65
Stefan Reinauerf96c2d92009-04-22 16:23:47 +000066char *acpigen_get_current(void)
67{
68 return gencurrent;
Rudolf Marek293b5f52009-02-01 18:35:15 +000069}
70
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +010071void acpigen_emit_byte(unsigned char b)
Rudolf Marek293b5f52009-02-01 18:35:15 +000072{
73 (*gencurrent++) = b;
Rudolf Marek293b5f52009-02-01 18:35:15 +000074}
75
Duncan Laurie9ccae752016-05-09 07:43:19 -070076void acpigen_emit_word(unsigned int data)
77{
78 acpigen_emit_byte(data & 0xff);
79 acpigen_emit_byte((data >> 8) & 0xff);
80}
81
82void acpigen_emit_dword(unsigned int data)
83{
84 acpigen_emit_byte(data & 0xff);
85 acpigen_emit_byte((data >> 8) & 0xff);
86 acpigen_emit_byte((data >> 16) & 0xff);
87 acpigen_emit_byte((data >> 24) & 0xff);
88}
89
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +010090void acpigen_write_package(int nr_el)
Rudolf Marek293b5f52009-02-01 18:35:15 +000091{
Rudolf Marek293b5f52009-02-01 18:35:15 +000092 /* package op */
93 acpigen_emit_byte(0x12);
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +010094 acpigen_write_len_f();
Rudolf Marek293b5f52009-02-01 18:35:15 +000095 acpigen_emit_byte(nr_el);
Rudolf Marek293b5f52009-02-01 18:35:15 +000096}
97
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +010098void acpigen_write_byte(unsigned int data)
Rudolf Marek293b5f52009-02-01 18:35:15 +000099{
100 /* byte op */
101 acpigen_emit_byte(0xa);
102 acpigen_emit_byte(data & 0xff);
Rudolf Marek293b5f52009-02-01 18:35:15 +0000103}
104
Duncan Laurie9ccae752016-05-09 07:43:19 -0700105void acpigen_write_word(unsigned int data)
106{
107 /* word op */
108 acpigen_emit_byte(0xb);
109 acpigen_emit_word(data);
110}
111
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100112void acpigen_write_dword(unsigned int data)
Rudolf Marek293b5f52009-02-01 18:35:15 +0000113{
114 /* dword op */
115 acpigen_emit_byte(0xc);
Duncan Laurie9ccae752016-05-09 07:43:19 -0700116 acpigen_emit_dword(data);
Rudolf Marek293b5f52009-02-01 18:35:15 +0000117}
118
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100119void acpigen_write_qword(uint64_t data)
Carl-Daniel Hailfingerd58671c2009-02-17 21:38:51 +0000120{
121 /* qword op */
122 acpigen_emit_byte(0xe);
Duncan Laurie9ccae752016-05-09 07:43:19 -0700123 acpigen_emit_dword(data & 0xffffffff);
124 acpigen_emit_dword((data >> 32) & 0xffffffff);
Carl-Daniel Hailfingerd58671c2009-02-17 21:38:51 +0000125}
126
Duncan Laurief7c38762016-05-09 08:20:38 -0700127void acpigen_write_zero(void)
128{
129 acpigen_emit_byte(0x00);
130}
131
132void acpigen_write_one(void)
133{
134 acpigen_emit_byte(0x01);
135}
136
137void acpigen_write_ones(void)
138{
139 acpigen_emit_byte(0xff);
140}
141
142void acpigen_write_integer(uint64_t data)
143{
144 if (data == 0)
145 acpigen_write_zero();
146 else if (data == 1)
147 acpigen_write_one();
148 else if (data <= 0xff)
149 acpigen_write_byte((unsigned char)data);
150 else if (data <= 0xffff)
151 acpigen_write_word((unsigned int)data);
152 else if (data <= 0xffffffff)
153 acpigen_write_dword((unsigned int)data);
154 else
155 acpigen_write_qword(data);
156}
157
158void acpigen_write_name_zero(const char *name)
159{
160 acpigen_write_name(name);
161 acpigen_write_one();
162}
163
164void acpigen_write_name_one(const char *name)
165{
166 acpigen_write_name(name);
167 acpigen_write_zero();
168}
169
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100170void acpigen_write_name_byte(const char *name, uint8_t val)
Stefan Reinauerf96c2d92009-04-22 16:23:47 +0000171{
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100172 acpigen_write_name(name);
173 acpigen_write_byte(val);
Rudolf Marek293b5f52009-02-01 18:35:15 +0000174}
175
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100176void acpigen_write_name_dword(const char *name, uint32_t val)
Stefan Reinauerf96c2d92009-04-22 16:23:47 +0000177{
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100178 acpigen_write_name(name);
179 acpigen_write_dword(val);
Rudolf Marek293b5f52009-02-01 18:35:15 +0000180}
181
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100182void acpigen_write_name_qword(const char *name, uint64_t val)
Stefan Reinauerf96c2d92009-04-22 16:23:47 +0000183{
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100184 acpigen_write_name(name);
185 acpigen_write_qword(val);
Carl-Daniel Hailfingerd58671c2009-02-17 21:38:51 +0000186}
187
Duncan Laurief7c38762016-05-09 08:20:38 -0700188void acpigen_write_name_integer(const char *name, uint64_t val)
189{
190 acpigen_write_name(name);
191 acpigen_write_integer(val);
192}
193
Duncan Laurie56b69aa2016-05-09 08:17:02 -0700194void acpigen_write_name_string(const char *name, const char *string)
195{
196 acpigen_write_name(name);
197 acpigen_write_string(string);
198}
199
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100200void acpigen_emit_stream(const char *data, int size)
Stefan Reinauerf96c2d92009-04-22 16:23:47 +0000201{
Rudolf Marek293b5f52009-02-01 18:35:15 +0000202 int i;
203 for (i = 0; i < size; i++) {
204 acpigen_emit_byte(data[i]);
205 }
Rudolf Marek293b5f52009-02-01 18:35:15 +0000206}
207
Duncan Laurie56b69aa2016-05-09 08:17:02 -0700208void acpigen_emit_string(const char *string)
209{
Jonathan Neuschäfer0ba307f2016-05-17 17:40:09 +0200210 acpigen_emit_stream(string, string ? strlen(string) : 0);
Duncan Laurie56b69aa2016-05-09 08:17:02 -0700211 acpigen_emit_byte('\0'); /* NUL */
212}
213
214void acpigen_write_string(const char *string)
215{
216 acpigen_emit_byte(0x0d);
217 acpigen_emit_string(string);
218}
219
Paul Menzel0f4c0e22013-02-22 12:33:08 +0100220/*
221 * The naming conventions for ACPI namespace names are a bit tricky as
222 * each element has to be 4 chars wide (»All names are a fixed 32 bits.«)
223 * and »By convention, when an ASL compiler pads a name shorter than 4
224 * characters, it is done so with trailing underscores (‘_’).«.
225 *
226 * Check sections 5.3, 18.2.2 and 18.4 of ACPI spec 3.0 for details.
227 */
Rudolf Marek3310d752009-06-21 20:26:13 +0000228
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100229static void acpigen_emit_simple_namestring(const char *name) {
230 int i;
Rudolf Marek3310d752009-06-21 20:26:13 +0000231 char ud[] = "____";
232 for (i = 0; i < 4; i++) {
233 if ((name[i] == '\0') || (name[i] == '.')) {
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100234 acpigen_emit_stream(ud, 4 - i);
Rudolf Marek3310d752009-06-21 20:26:13 +0000235 break;
236 } else {
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100237 acpigen_emit_byte(name[i]);
Rudolf Marek3310d752009-06-21 20:26:13 +0000238 }
239 }
Rudolf Marek3310d752009-06-21 20:26:13 +0000240}
241
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100242static void acpigen_emit_double_namestring(const char *name, int dotpos) {
Rudolf Marek3310d752009-06-21 20:26:13 +0000243 /* mark dual name prefix */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100244 acpigen_emit_byte(0x2e);
245 acpigen_emit_simple_namestring(name);
246 acpigen_emit_simple_namestring(&name[dotpos + 1]);
Rudolf Marek3310d752009-06-21 20:26:13 +0000247}
248
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100249static void acpigen_emit_multi_namestring(const char *name) {
250 int count = 0;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000251 unsigned char *pathlen;
Rudolf Marek3310d752009-06-21 20:26:13 +0000252 /* mark multi name prefix */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100253 acpigen_emit_byte(0x2f);
254 acpigen_emit_byte(0x0);
Rudolf Marek3310d752009-06-21 20:26:13 +0000255 pathlen = ((unsigned char *) acpigen_get_current()) - 1;
256
257 while (name[0] != '\0') {
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100258 acpigen_emit_simple_namestring(name);
Rudolf Marek3310d752009-06-21 20:26:13 +0000259 /* find end or next entity */
260 while ((name[0] != '.') && (name[0] != '\0'))
261 name++;
262 /* forward to next */
263 if (name[0] == '.')
264 name++;
265 count++;
266 }
267
268 pathlen[0] = count;
Rudolf Marek3310d752009-06-21 20:26:13 +0000269}
270
271
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100272void acpigen_emit_namestring(const char *namepath) {
Rudolf Marek3310d752009-06-21 20:26:13 +0000273 int dotcount = 0, i;
Myles Watson3fe6b702009-10-09 20:13:43 +0000274 int dotpos = 0;
Rudolf Marek3310d752009-06-21 20:26:13 +0000275
Ronald G. Minnichbe738eb2013-03-07 11:05:28 -0600276 /* We can start with a '\'. */
Rudolf Marek3310d752009-06-21 20:26:13 +0000277 if (namepath[0] == '\\') {
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100278 acpigen_emit_byte('\\');
Rudolf Marek3310d752009-06-21 20:26:13 +0000279 namepath++;
280 }
281
Ronald G. Minnichbe738eb2013-03-07 11:05:28 -0600282 /* And there can be any number of '^' */
Rudolf Marek3310d752009-06-21 20:26:13 +0000283 while (namepath[0] == '^') {
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100284 acpigen_emit_byte('^');
Rudolf Marek3310d752009-06-21 20:26:13 +0000285 namepath++;
286 }
287
Vladimir Serbinenkod942ed92014-08-30 20:44:37 +0200288 /* If we have only \\ or only ^...^. Then we need to put a null
289 name (0x00). */
290 if(namepath[0] == '\0') {
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100291 acpigen_emit_byte(0x00);
292 return;
Vladimir Serbinenkod942ed92014-08-30 20:44:37 +0200293 }
Rudolf Marek3310d752009-06-21 20:26:13 +0000294
295 i = 0;
296 while (namepath[i] != '\0') {
297 if (namepath[i] == '.') {
298 dotcount++;
299 dotpos = i;
300 }
301 i++;
302 }
303
304 if (dotcount == 0) {
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100305 acpigen_emit_simple_namestring(namepath);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000306 } else if (dotcount == 1) {
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100307 acpigen_emit_double_namestring(namepath, dotpos);
Rudolf Marek3310d752009-06-21 20:26:13 +0000308 } else {
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100309 acpigen_emit_multi_namestring(namepath);
Rudolf Marek3310d752009-06-21 20:26:13 +0000310 }
Rudolf Marek3310d752009-06-21 20:26:13 +0000311}
312
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100313void acpigen_write_name(const char *name)
Rudolf Marek293b5f52009-02-01 18:35:15 +0000314{
Rudolf Marek293b5f52009-02-01 18:35:15 +0000315 /* name op */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100316 acpigen_emit_byte(0x8);
317 acpigen_emit_namestring(name);
Rudolf Marek293b5f52009-02-01 18:35:15 +0000318}
319
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100320void acpigen_write_scope(const char *name)
Rudolf Marek293b5f52009-02-01 18:35:15 +0000321{
Rudolf Marek293b5f52009-02-01 18:35:15 +0000322 /* scope op */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100323 acpigen_emit_byte(0x10);
324 acpigen_write_len_f();
325 acpigen_emit_namestring(name);
Rudolf Marek293b5f52009-02-01 18:35:15 +0000326}
Rudolf Marekf997b552009-02-14 15:40:23 +0000327
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100328void acpigen_write_processor(u8 cpuindex, u32 pblock_addr, u8 pblock_len)
Rudolf Marekf997b552009-02-14 15:40:23 +0000329{
330/*
331 Processor (\_PR.CPUcpuindex, cpuindex, pblock_addr, pblock_len)
332 {
333*/
334 char pscope[16];
Rudolf Marekf997b552009-02-14 15:40:23 +0000335 /* processor op */
336 acpigen_emit_byte(0x5b);
337 acpigen_emit_byte(0x83);
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100338 acpigen_write_len_f();
Rudolf Marekf997b552009-02-14 15:40:23 +0000339
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100340 snprintf(pscope, sizeof (pscope),
Timothy Pearson033bb4b2015-02-10 22:21:39 -0600341 "\\_PR.CP%02d", (unsigned int) cpuindex);
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100342 acpigen_emit_namestring(pscope);
Rudolf Marekf997b552009-02-14 15:40:23 +0000343 acpigen_emit_byte(cpuindex);
Duncan Laurie9ccae752016-05-09 07:43:19 -0700344 acpigen_emit_dword(pblock_addr);
Rudolf Marekf997b552009-02-14 15:40:23 +0000345 acpigen_emit_byte(pblock_len);
Rudolf Marekf997b552009-02-14 15:40:23 +0000346}
347
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100348void acpigen_write_empty_PCT(void)
Rudolf Marekf997b552009-02-14 15:40:23 +0000349{
350/*
351 Name (_PCT, Package (0x02)
352 {
353 ResourceTemplate ()
354 {
355 Register (FFixedHW,
356 0x00, // Bit Width
357 0x00, // Bit Offset
358 0x0000000000000000, // Address
359 ,)
360 },
361
362 ResourceTemplate ()
363 {
364 Register (FFixedHW,
365 0x00, // Bit Width
366 0x00, // Bit Offset
367 0x0000000000000000, // Address
368 ,)
369 }
370 })
371*/
372 static char stream[] = {
373 0x08, 0x5F, 0x50, 0x43, 0x54, 0x12, 0x2C, /* 00000030 "0._PCT.," */
374 0x02, 0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, /* 00000038 "........" */
375 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00000040 "........" */
376 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14, /* 00000048 "....y..." */
377 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00, /* 00000050 "........" */
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00000058 "........" */
379 0x00, 0x79, 0x00
380 };
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100381 acpigen_emit_stream(stream, ARRAY_SIZE(stream));
Rudolf Marekf997b552009-02-14 15:40:23 +0000382}
383
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100384void acpigen_write_empty_PTC(void)
Stefan Reinauer39205c62012-04-27 21:49:28 +0200385{
386/*
387 Name (_PTC, Package (0x02)
388 {
389 ResourceTemplate ()
390 {
391 Register (FFixedHW,
392 0x00, // Bit Width
393 0x00, // Bit Offset
394 0x0000000000000000, // Address
395 ,)
396 },
397
398 ResourceTemplate ()
399 {
400 Register (FFixedHW,
401 0x00, // Bit Width
402 0x00, // Bit Offset
403 0x0000000000000000, // Address
404 ,)
405 }
406 })
407*/
Stefan Reinauer39205c62012-04-27 21:49:28 +0200408 acpi_addr_t addr = {
409 .space_id = ACPI_ADDRESS_SPACE_FIXED,
410 .bit_width = 0,
411 .bit_offset = 0,
zbaoee8a9f6c2012-05-29 14:59:38 +0800412 {
413 .resv = 0
414 },
Stefan Reinauer39205c62012-04-27 21:49:28 +0200415 .addrl = 0,
416 .addrh = 0,
417 };
418
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100419 acpigen_write_name("_PTC");
420 acpigen_write_package(2);
Stefan Reinauer39205c62012-04-27 21:49:28 +0200421
422 /* ControlRegister */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100423 acpigen_write_resourcetemplate_header();
424 acpigen_write_register(&addr);
425 acpigen_write_resourcetemplate_footer();
Stefan Reinauer39205c62012-04-27 21:49:28 +0200426
427 /* StatusRegister */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100428 acpigen_write_resourcetemplate_header();
429 acpigen_write_register(&addr);
430 acpigen_write_resourcetemplate_footer();
Stefan Reinauer39205c62012-04-27 21:49:28 +0200431
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100432 acpigen_pop_len();
Stefan Reinauer39205c62012-04-27 21:49:28 +0200433}
434
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100435void acpigen_write_method(const char *name, int nargs)
Vladimir Serbinenko80fb8ed2014-11-05 10:28:28 +0100436{
Vladimir Serbinenko80fb8ed2014-11-05 10:28:28 +0100437 /* method op */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100438 acpigen_emit_byte(0x14);
439 acpigen_write_len_f();
440 acpigen_emit_namestring(name);
441 acpigen_emit_byte(nargs & 7);
Vladimir Serbinenko80fb8ed2014-11-05 10:28:28 +0100442}
443
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100444void acpigen_write_device(const char *name)
Vladimir Serbinenko663be6e2014-11-05 21:29:45 +0100445{
Duncan Laurie9ccae752016-05-09 07:43:19 -0700446 /* device op */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100447 acpigen_emit_byte(0x5b);
448 acpigen_emit_byte(0x82);
449 acpigen_write_len_f();
450 acpigen_emit_namestring(name);
Vladimir Serbinenko663be6e2014-11-05 21:29:45 +0100451}
452
Duncan Laurieabe2de82016-05-09 11:08:46 -0700453void acpigen_write_STA(uint8_t status)
454{
455 /*
456 * Method (_STA, 0, NotSerialized) { Return (status) }
457 */
458 acpigen_write_method("_STA", 0);
459 acpigen_emit_byte(0xa4);
460 acpigen_write_byte(status);
461 acpigen_pop_len();
462}
463
Paul Menzel0f4c0e22013-02-22 12:33:08 +0100464/*
465 * Generates a func with max supported P-states.
466 */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100467void acpigen_write_PPC(u8 nr)
Rudolf Marekf997b552009-02-14 15:40:23 +0000468{
469/*
470 Method (_PPC, 0, NotSerialized)
471 {
472 Return (nr)
473 }
474*/
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100475 acpigen_write_method("_PPC", 0);
Rudolf Marekf997b552009-02-14 15:40:23 +0000476 /* return */
477 acpigen_emit_byte(0xa4);
478 /* arg */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100479 acpigen_write_byte(nr);
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100480 acpigen_pop_len();
Rudolf Marekf997b552009-02-14 15:40:23 +0000481}
482
Paul Menzel0f4c0e22013-02-22 12:33:08 +0100483/*
484 * Generates a func with max supported P-states saved
485 * in the variable PPCM.
486 */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100487void acpigen_write_PPC_NVS(void)
Duncan Laurie0eefa002012-07-16 12:11:53 -0700488{
489/*
490 Method (_PPC, 0, NotSerialized)
491 {
492 Return (PPCM)
493 }
494*/
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100495 acpigen_write_method("_PPC", 0);
Duncan Laurie0eefa002012-07-16 12:11:53 -0700496 /* return */
497 acpigen_emit_byte(0xa4);
498 /* arg */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100499 acpigen_emit_namestring("PPCM");
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100500 acpigen_pop_len();
Duncan Laurie0eefa002012-07-16 12:11:53 -0700501}
502
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100503void acpigen_write_TPC(const char *gnvs_tpc_limit)
Stefan Reinauer39205c62012-04-27 21:49:28 +0200504{
505/*
506 // Sample _TPC method
507 Method (_TPC, 0, NotSerialized)
508 {
509 Return (\TLVL)
510 }
511 */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100512 acpigen_write_method("_TPC", 0);
513 acpigen_emit_byte(0xa4); /* ReturnOp */
514 acpigen_emit_namestring(gnvs_tpc_limit);
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100515 acpigen_pop_len();
Stefan Reinauer39205c62012-04-27 21:49:28 +0200516}
517
Duncan Laurieabe2de82016-05-09 11:08:46 -0700518void acpigen_write_PRW(u32 wake, u32 level)
519{
520 /*
521 * Name (_PRW, Package () { wake, level }
522 */
523 acpigen_write_name("_PRW");
524 acpigen_write_package(2);
525 acpigen_write_integer(wake);
526 acpigen_write_integer(level);
527 acpigen_pop_len();
528}
529
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100530void acpigen_write_PSS_package(u32 coreFreq, u32 power, u32 transLat,
Stefan Reinauerf96c2d92009-04-22 16:23:47 +0000531 u32 busmLat, u32 control, u32 status)
Rudolf Marekf997b552009-02-14 15:40:23 +0000532{
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100533 acpigen_write_package(6);
534 acpigen_write_dword(coreFreq);
535 acpigen_write_dword(power);
536 acpigen_write_dword(transLat);
537 acpigen_write_dword(busmLat);
538 acpigen_write_dword(control);
539 acpigen_write_dword(status);
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100540 acpigen_pop_len();
Stefan Reinauerd4bacf92012-05-02 16:38:47 -0700541
542 printk(BIOS_DEBUG, "PSS: %uMHz power %u control 0x%x status 0x%x\n",
543 coreFreq, power, control, status);
Rudolf Marekf997b552009-02-14 15:40:23 +0000544}
Patrick Georgidf444bf2009-04-21 20:34:36 +0000545
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100546void acpigen_write_PSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
Patrick Georgidf444bf2009-04-21 20:34:36 +0000547{
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100548 acpigen_write_name("_PSD");
549 acpigen_write_package(1);
550 acpigen_write_package(5);
551 acpigen_write_byte(5); // 5 values
552 acpigen_write_byte(0); // revision 0
553 acpigen_write_dword(domain);
554 acpigen_write_dword(coordtype);
555 acpigen_write_dword(numprocs);
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100556 acpigen_pop_len();
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100557 acpigen_pop_len();
Patrick Georgidf444bf2009-04-21 20:34:36 +0000558}
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000559
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100560void acpigen_write_CST_package_entry(acpi_cstate_t *cstate)
Sven Schnelle0b86c762011-10-21 21:46:47 +0200561{
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100562 acpigen_write_package(4);
563 acpigen_write_resourcetemplate_header();
Stefan Reinauer4cc8c702012-04-27 21:34:16 +0200564 acpigen_write_register(&cstate->resource);
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100565 acpigen_write_resourcetemplate_footer();
566 acpigen_write_dword(cstate->ctype);
567 acpigen_write_dword(cstate->latency);
568 acpigen_write_dword(cstate->power);
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100569 acpigen_pop_len();
Sven Schnelle0b86c762011-10-21 21:46:47 +0200570}
571
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100572void acpigen_write_CST_package(acpi_cstate_t *cstate, int nentries)
Sven Schnelle0b86c762011-10-21 21:46:47 +0200573{
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100574 int i;
575 acpigen_write_name("_CST");
576 acpigen_write_package(nentries+1);
577 acpigen_write_dword(nentries);
Sven Schnelle0b86c762011-10-21 21:46:47 +0200578
579 for (i = 0; i < nentries; i++)
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100580 acpigen_write_CST_package_entry(cstate + i);
Sven Schnelle0b86c762011-10-21 21:46:47 +0200581
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100582 acpigen_pop_len();
Sven Schnelle0b86c762011-10-21 21:46:47 +0200583}
584
Timothy Pearson83abd812015-06-08 19:35:06 -0500585void acpigen_write_CSD_package(u32 domain, u32 numprocs, CSD_coord coordtype, u32 index)
586{
587 acpigen_write_name("_CSD");
588 acpigen_write_package(1);
589 acpigen_write_package(6);
590 acpigen_write_byte(6); // 6 values
591 acpigen_write_byte(0); // revision 0
592 acpigen_write_dword(domain);
593 acpigen_write_dword(coordtype);
594 acpigen_write_dword(numprocs);
595 acpigen_write_dword(index);
596 acpigen_pop_len();
597 acpigen_pop_len();
598}
599
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100600void acpigen_write_TSS_package(int entries, acpi_tstate_t *tstate_list)
Stefan Reinauer39205c62012-04-27 21:49:28 +0200601{
602/*
603 Sample _TSS package with 100% and 50% duty cycles
604 Name (_TSS, Package (0x02)
605 {
606 Package(){100, 1000, 0, 0x00, 0)
607 Package(){50, 520, 0, 0x18, 0)
608 })
609 */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100610 int i;
Stefan Reinauer39205c62012-04-27 21:49:28 +0200611 acpi_tstate_t *tstate = tstate_list;
612
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100613 acpigen_write_name("_TSS");
614 acpigen_write_package(entries);
Stefan Reinauer39205c62012-04-27 21:49:28 +0200615
616 for (i = 0; i < entries; i++) {
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100617 acpigen_write_package(5);
618 acpigen_write_dword(tstate->percent);
619 acpigen_write_dword(tstate->power);
620 acpigen_write_dword(tstate->latency);
621 acpigen_write_dword(tstate->control);
622 acpigen_write_dword(tstate->status);
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100623 acpigen_pop_len();
Stefan Reinauer39205c62012-04-27 21:49:28 +0200624 tstate++;
Stefan Reinauer39205c62012-04-27 21:49:28 +0200625 }
626
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100627 acpigen_pop_len();
Stefan Reinauer39205c62012-04-27 21:49:28 +0200628}
629
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100630void acpigen_write_TSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
Stefan Reinauer39205c62012-04-27 21:49:28 +0200631{
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100632 acpigen_write_name("_TSD");
633 acpigen_write_package(1);
634 acpigen_write_package(5);
635 acpigen_write_byte(5); // 5 values
636 acpigen_write_byte(0); // revision 0
637 acpigen_write_dword(domain);
638 acpigen_write_dword(coordtype);
639 acpigen_write_dword(numprocs);
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100640 acpigen_pop_len();
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100641 acpigen_pop_len();
Stefan Reinauer39205c62012-04-27 21:49:28 +0200642}
643
644
645
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100646void acpigen_write_mem32fixed(int readwrite, u32 base, u32 size)
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000647{
648 /*
649 * acpi 4.0 section 6.4.3.4: 32-Bit Fixed Memory Range Descriptor
650 * Byte 0:
651 * Bit7 : 1 => big item
652 * Bit6-0: 0000110 (0x6) => 32-bit fixed memory
653 */
654 acpigen_emit_byte(0x86);
655 /* Byte 1+2: length (0x0009) */
656 acpigen_emit_byte(0x09);
657 acpigen_emit_byte(0x00);
658 /* bit1-7 are ignored */
659 acpigen_emit_byte(readwrite ? 0x01 : 0x00);
Duncan Laurie9ccae752016-05-09 07:43:19 -0700660 acpigen_emit_dword(base);
661 acpigen_emit_dword(size);
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000662}
663
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100664void acpigen_write_register(acpi_addr_t *addr)
Sven Schnelle0b86c762011-10-21 21:46:47 +0200665{
Stefan Reinauer4cc8c702012-04-27 21:34:16 +0200666 acpigen_emit_byte(0x82); /* Register Descriptor */
667 acpigen_emit_byte(0x0c); /* Register Length 7:0 */
668 acpigen_emit_byte(0x00); /* Register Length 15:8 */
669 acpigen_emit_byte(addr->space_id); /* Address Space ID */
670 acpigen_emit_byte(addr->bit_width); /* Register Bit Width */
671 acpigen_emit_byte(addr->bit_offset); /* Register Bit Offset */
672 acpigen_emit_byte(addr->resv); /* Register Access Size */
Duncan Laurie9ccae752016-05-09 07:43:19 -0700673 acpigen_emit_dword(addr->addrl); /* Register Address Low */
674 acpigen_emit_dword(addr->addrh); /* Register Address High */
Sven Schnelle0b86c762011-10-21 21:46:47 +0200675}
676
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100677void acpigen_write_irq(u16 mask)
Vladimir Serbinenko20ea0402014-02-15 18:57:17 +0100678{
679 /*
680 * acpi 3.0b section 6.4.2.1: IRQ Descriptor
681 * Byte 0:
682 * Bit7 : 0 => small item
683 * Bit6-3: 0100 (0x4) => IRQ port descriptor
684 * Bit2-0: 010 (0x2) => 2 Bytes long
685 */
686 acpigen_emit_byte(0x22);
687 acpigen_emit_byte(mask & 0xff);
688 acpigen_emit_byte((mask >> 8) & 0xff);
Vladimir Serbinenko20ea0402014-02-15 18:57:17 +0100689}
690
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100691void acpigen_write_io16(u16 min, u16 max, u8 align, u8 len, u8 decode16)
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000692{
693 /*
694 * acpi 4.0 section 6.4.2.6: I/O Port Descriptor
695 * Byte 0:
696 * Bit7 : 0 => small item
697 * Bit6-3: 1000 (0x8) => I/O port descriptor
698 * Bit2-0: 111 (0x7) => 7 Bytes long
699 */
700 acpigen_emit_byte(0x47);
Paul Menzel0f4c0e22013-02-22 12:33:08 +0100701 /* Does the device decode all 16 or just 10 bits? */
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000702 /* bit1-7 are ignored */
703 acpigen_emit_byte(decode16 ? 0x01 : 0x00);
704 /* minimum base address the device may be configured for */
705 acpigen_emit_byte(min & 0xff);
706 acpigen_emit_byte((min >> 8) & 0xff);
707 /* maximum base address the device may be configured for */
708 acpigen_emit_byte(max & 0xff);
709 acpigen_emit_byte((max >> 8) & 0xff);
710 /* alignment for min base */
711 acpigen_emit_byte(align & 0xff);
712 acpigen_emit_byte(len & 0xff);
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000713}
714
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100715void acpigen_write_resourcetemplate_header(void)
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000716{
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000717 /*
718 * A ResourceTemplate() is a Buffer() with a
719 * (Byte|Word|DWord) containing the length, followed by one or more
Paul Menzel0f4c0e22013-02-22 12:33:08 +0100720 * resource items, terminated by the end tag.
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000721 * (small item 0xf, len 1)
722 */
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100723 acpigen_emit_byte(0x11); /* Buffer opcode */
724 acpigen_write_len_f();
725 acpigen_emit_byte(0x0b); /* Word opcode */
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000726 len_stack[ltop++] = acpigen_get_current();
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100727 acpigen_emit_byte(0x00);
728 acpigen_emit_byte(0x00);
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000729}
730
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100731void acpigen_write_resourcetemplate_footer(void)
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000732{
733 char *p = len_stack[--ltop];
Vladimir Serbinenko9acc1e82014-11-09 03:37:28 +0100734 int len;
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000735 /*
736 * end tag (acpi 4.0 Section 6.4.2.8)
737 * 0x79 <checksum>
738 * 0x00 is treated as a good checksum according to the spec
739 * and is what iasl generates.
740 */
Vladimir Serbinenko9acc1e82014-11-09 03:37:28 +0100741 acpigen_emit_byte(0x79);
742 acpigen_emit_byte(0x00);
743
Martin Rothe3690102016-01-06 15:21:02 -0700744 len = gencurrent - p;
Vladimir Serbinenko9acc1e82014-11-09 03:37:28 +0100745
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000746 /* patch len word */
Vladimir Serbinenko9acc1e82014-11-09 03:37:28 +0100747 p[0] = len & 0xff;
748 p[1] = (len >> 8) & 0xff;
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000749 /* patch len field */
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100750 acpigen_pop_len();
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000751}
752
753static void acpigen_add_mainboard_rsvd_mem32(void *gp, struct device *dev,
754 struct resource *res)
755{
756 acpigen_write_mem32fixed(0, res->base, res->size);
757}
758
759static void acpigen_add_mainboard_rsvd_io(void *gp, struct device *dev,
760 struct resource *res)
761{
762 resource_t base = res->base;
763 resource_t size = res->size;
764 while (size > 0) {
765 resource_t sz = size > 255 ? 255 : size;
766 acpigen_write_io16(base, base, 0, sz, 1);
767 size -= sz;
768 base += sz;
769 }
770}
771
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100772void acpigen_write_mainboard_resource_template(void)
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000773{
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100774 acpigen_write_resourcetemplate_header();
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000775
Paul Menzel0f4c0e22013-02-22 12:33:08 +0100776 /* Add reserved memory ranges. */
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000777 search_global_resources(
778 IORESOURCE_MEM | IORESOURCE_RESERVE,
779 IORESOURCE_MEM | IORESOURCE_RESERVE,
780 acpigen_add_mainboard_rsvd_mem32, 0);
781
Paul Menzel0f4c0e22013-02-22 12:33:08 +0100782 /* Add reserved io ranges. */
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000783 search_global_resources(
784 IORESOURCE_IO | IORESOURCE_RESERVE,
785 IORESOURCE_IO | IORESOURCE_RESERVE,
786 acpigen_add_mainboard_rsvd_io, 0);
787
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100788 acpigen_write_resourcetemplate_footer();
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000789}
790
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100791void acpigen_write_mainboard_resources(const char *scope, const char *name)
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000792{
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100793 acpigen_write_scope(scope);
794 acpigen_write_name(name);
795 acpigen_write_mainboard_resource_template();
Vladimir Serbinenkoa09f4db2014-11-09 03:32:58 +0100796 acpigen_pop_len();
Tobias Diedrich0fe6e9a2010-11-17 16:27:06 +0000797}
Vladimir Serbinenko8ecdc9e2014-02-15 18:59:40 +0100798
799static int hex2bin(const char c)
800{
801 if (c >= 'A' && c <= 'F')
802 return c - 'A' + 10;
803 if (c >= 'a' && c <= 'f')
804 return c - 'a' + 10;
805 return c - '0';
806}
807
Vladimir Serbinenko9bb5c5c2014-11-09 03:51:32 +0100808void acpigen_emit_eisaid(const char *eisaid)
Vladimir Serbinenko8ecdc9e2014-02-15 18:59:40 +0100809{
810 u32 compact = 0;
811
812 /* Clamping individual values would be better but
813 there is a disagreement over what is a valid
814 EISA id, so accept anything and don't clamp,
815 parent code should create a valid EISAid.
816 */
817 compact |= (eisaid[0] - 'A' + 1) << 26;
818 compact |= (eisaid[1] - 'A' + 1) << 21;
819 compact |= (eisaid[2] - 'A' + 1) << 16;
820 compact |= hex2bin(eisaid[3]) << 12;
821 compact |= hex2bin(eisaid[4]) << 8;
822 compact |= hex2bin(eisaid[5]) << 4;
823 compact |= hex2bin(eisaid[6]);
824
825 acpigen_emit_byte(0xc);
826 acpigen_emit_byte((compact >> 24) & 0xff);
827 acpigen_emit_byte((compact >> 16) & 0xff);
828 acpigen_emit_byte((compact >> 8) & 0xff);
829 acpigen_emit_byte(compact & 0xff);
Vladimir Serbinenko8ecdc9e2014-02-15 18:59:40 +0100830}
Duncan Laurie3829f232016-05-09 11:08:46 -0700831
832/*
833 * ToUUID(uuid)
834 *
835 * ACPI 6.1 Section 19.6.136 table 19-385 defines a special output
836 * order for the bytes that make up a UUID Buffer object.
837 * UUID byte order for input:
838 * aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
839 * UUID byte order for output:
840 * ddccbbaa-ffee-hhgg-iijj-kkllmmnnoopp
841 */
842#define UUID_LEN 16
843void acpigen_write_uuid(const char *uuid)
844{
845 uint8_t buf[UUID_LEN];
846 size_t i, order[UUID_LEN] = { 3, 2, 1, 0, 5, 4, 7, 6,
847 8, 9, 10, 11, 12, 13, 14, 15 };
848
849 /* Parse UUID string into bytes */
850 if (hexstrtobin(uuid, buf, UUID_LEN) < UUID_LEN)
851 return;
852
853 /* BufferOp */
854 acpigen_emit_byte(0x11);
855 acpigen_write_len_f();
856
857 /* Buffer length in bytes */
858 acpigen_write_word(UUID_LEN);
859
860 /* Output UUID in expected order */
861 for (i = 0; i < UUID_LEN; i++)
862 acpigen_emit_byte(buf[order[i]]);
863
864 acpigen_pop_len();
865}