exconvrt.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:15k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: exconvrt - Object conversion routines
  4.  *              $Revision: 24 $
  5.  *
  6.  *****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 R. Byron Moore
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include "acpi.h"
  25. #include "acparser.h"
  26. #include "acnamesp.h"
  27. #include "acinterp.h"
  28. #include "acevents.h"
  29. #include "amlcode.h"
  30. #include "acdispat.h"
  31. #define _COMPONENT          ACPI_EXECUTER
  32.  MODULE_NAME         ("exconvrt")
  33. /*******************************************************************************
  34.  *
  35.  * FUNCTION:    Acpi_ex_convert_to_integer
  36.  *
  37.  * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
  38.  *                                Integer, Buffer, or String
  39.  *              Walk_state      - Current method state
  40.  *
  41.  * RETURN:      Status
  42.  *
  43.  * DESCRIPTION: Convert an ACPI Object to an integer.
  44.  *
  45.  ******************************************************************************/
  46. acpi_status
  47. acpi_ex_convert_to_integer (
  48. acpi_operand_object     *obj_desc,
  49. acpi_operand_object     **result_desc,
  50. acpi_walk_state         *walk_state)
  51. {
  52. u32                     i;
  53. acpi_operand_object     *ret_desc;
  54. u32                     count;
  55. char                    *pointer;
  56. acpi_integer            result;
  57. u32                     integer_size = sizeof (acpi_integer);
  58. FUNCTION_ENTRY ();
  59. switch (obj_desc->common.type) {
  60. case ACPI_TYPE_INTEGER:
  61. *result_desc = obj_desc;
  62. return (AE_OK);
  63. case ACPI_TYPE_STRING:
  64. pointer = obj_desc->string.pointer;
  65. count   = obj_desc->string.length;
  66. break;
  67. case ACPI_TYPE_BUFFER:
  68. pointer = (char *) obj_desc->buffer.pointer;
  69. count   = obj_desc->buffer.length;
  70. break;
  71. default:
  72. return (AE_TYPE);
  73. }
  74. /*
  75.  * Create a new integer
  76.  */
  77. ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
  78. if (!ret_desc) {
  79. return (AE_NO_MEMORY);
  80. }
  81. /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
  82. if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
  83. /*
  84.  * We are running a method that exists in a 32-bit ACPI table.
  85.  * Truncate the value to 32 bits by zeroing out the upper 32-bit field
  86.  */
  87. integer_size = sizeof (u32);
  88. }
  89. /*
  90.  * Convert the buffer/string to an integer.  Note that both buffers and
  91.  * strings are treated as raw data - we don't convert ascii to hex for
  92.  * strings.
  93.  *
  94.  * There are two terminating conditions for the loop:
  95.  * 1) The size of an integer has been reached, or
  96.  * 2) The end of the buffer or string has been reached
  97.  */
  98. result = 0;
  99. /* Transfer no more than an integer's worth of data */
  100. if (count > integer_size) {
  101. count = integer_size;
  102. }
  103. /*
  104.  * String conversion is different than Buffer conversion
  105.  */
  106. switch (obj_desc->common.type) {
  107. case ACPI_TYPE_STRING:
  108. /* TBD: Need to use 64-bit STRTOUL */
  109. /*
  110.  * Convert string to an integer
  111.  * String must be hexadecimal as per the ACPI specification
  112.  */
  113. result = STRTOUL (pointer, NULL, 16);
  114. break;
  115. case ACPI_TYPE_BUFFER:
  116. /*
  117.  * Buffer conversion - we simply grab enough raw data from the
  118.  * buffer to fill an integer
  119.  */
  120. for (i = 0; i < count; i++) {
  121. /*
  122.  * Get next byte and shift it into the Result.
  123.  * Little endian is used, meaning that the first byte of the buffer
  124.  * is the LSB of the integer
  125.  */
  126. result |= (((acpi_integer) pointer[i]) << (i * 8));
  127. }
  128. break;
  129. }
  130. /* Save the Result, delete original descriptor, store new descriptor */
  131. ret_desc->integer.value = result;
  132. if (*result_desc == obj_desc) {
  133. if (walk_state->opcode != AML_STORE_OP) {
  134. acpi_ut_remove_reference (obj_desc);
  135. }
  136. }
  137. *result_desc = ret_desc;
  138. return (AE_OK);
  139. }
  140. /*******************************************************************************
  141.  *
  142.  * FUNCTION:    Acpi_ex_convert_to_buffer
  143.  *
  144.  * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
  145.  *                                Integer, Buffer, or String
  146.  *              Walk_state      - Current method state
  147.  *
  148.  * RETURN:      Status
  149.  *
  150.  * DESCRIPTION: Convert an ACPI Object to an Buffer
  151.  *
  152.  ******************************************************************************/
  153. acpi_status
  154. acpi_ex_convert_to_buffer (
  155. acpi_operand_object     *obj_desc,
  156. acpi_operand_object     **result_desc,
  157. acpi_walk_state         *walk_state)
  158. {
  159. acpi_operand_object     *ret_desc;
  160. u32                     i;
  161. u32                     integer_size = sizeof (acpi_integer);
  162. u8                      *new_buf;
  163. FUNCTION_ENTRY ();
  164. switch (obj_desc->common.type) {
  165. case ACPI_TYPE_INTEGER:
  166. /*
  167.  * Create a new Buffer
  168.  */
  169. ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
  170. if (!ret_desc) {
  171. return (AE_NO_MEMORY);
  172. }
  173. /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
  174. if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
  175. /*
  176.  * We are running a method that exists in a 32-bit ACPI table.
  177.  * Truncate the value to 32 bits by zeroing out the upper
  178.  * 32-bit field
  179.  */
  180. integer_size = sizeof (u32);
  181. }
  182. /* Need enough space for one integers */
  183. ret_desc->buffer.length = integer_size;
  184. new_buf = ACPI_MEM_CALLOCATE (integer_size);
  185. if (!new_buf) {
  186. REPORT_ERROR
  187. (("Ex_convert_to_buffer: Buffer allocation failuren"));
  188. acpi_ut_remove_reference (ret_desc);
  189. return (AE_NO_MEMORY);
  190. }
  191. /* Copy the integer to the buffer */
  192. for (i = 0; i < integer_size; i++) {
  193. new_buf[i] = (u8) (obj_desc->integer.value >> (i * 8));
  194. }
  195. ret_desc->buffer.pointer = new_buf;
  196. /* Return the new buffer descriptor */
  197. if (*result_desc == obj_desc) {
  198. if (walk_state->opcode != AML_STORE_OP) {
  199. acpi_ut_remove_reference (obj_desc);
  200. }
  201. }
  202. *result_desc = ret_desc;
  203. break;
  204. case ACPI_TYPE_STRING:
  205. *result_desc = obj_desc;
  206. break;
  207. case ACPI_TYPE_BUFFER:
  208. *result_desc = obj_desc;
  209. break;
  210. default:
  211. return (AE_TYPE);
  212. break;
  213.    }
  214. return (AE_OK);
  215. }
  216. /*******************************************************************************
  217.  *
  218.  * FUNCTION:    Acpi_ex_convert_ascii
  219.  *
  220.  * PARAMETERS:  Integer
  221.  *
  222.  * RETURN:      Actual string length
  223.  *
  224.  * DESCRIPTION: Convert an ACPI Integer to a hex string
  225.  *
  226.  ******************************************************************************/
  227. u32
  228. acpi_ex_convert_to_ascii (
  229. acpi_integer            integer,
  230. u32                     base,
  231. u8                      *string)
  232. {
  233. u32                     i;
  234. u32                     j;
  235. u32                     k = 0;
  236. u8                      hex_digit;
  237. acpi_integer            digit;
  238. u32                     remainder;
  239. u32                     length = sizeof (acpi_integer);
  240. u8                      leading_zero = TRUE;
  241. FUNCTION_ENTRY ();
  242. switch (base) {
  243. case 10:
  244. remainder = 0;
  245. for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0 ; i--) {
  246. /* Divide by nth factor of 10 */
  247. digit = integer;
  248. for (j = 1; j < i; j++) {
  249. acpi_ut_short_divide (&digit, 10, &digit, &remainder);
  250. }
  251. /* Create the decimal digit */
  252. if (digit != 0) {
  253. leading_zero = FALSE;
  254. }
  255. if (!leading_zero) {
  256. string[k] = (u8) (ASCII_ZERO + remainder);
  257. k++;
  258. }
  259. }
  260. break;
  261. case 16:
  262. /* Copy the integer to the buffer */
  263. for (i = 0, j = ((length * 2) -1); i < (length * 2); i++, j--) {
  264. hex_digit = acpi_ut_hex_to_ascii_char (integer, (j * 4));
  265. if (hex_digit != ASCII_ZERO) {
  266. leading_zero = FALSE;
  267. }
  268. if (!leading_zero) {
  269. string[k] = hex_digit;
  270. k++;
  271. }
  272. }
  273. break;
  274. default:
  275. break;
  276. }
  277. /*
  278.  * Since leading zeros are supressed, we must check for the case where
  279.  * the integer equals 0.
  280.  *
  281.  * Finally, null terminate the string and return the length
  282.  */
  283. if (!k) {
  284. string [0] = ASCII_ZERO;
  285. k = 1;
  286. }
  287. string [k] = 0;
  288. return (k);
  289. }
  290. /*******************************************************************************
  291.  *
  292.  * FUNCTION:    Acpi_ex_convert_to_string
  293.  *
  294.  * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
  295.  *                                Integer, Buffer, or String
  296.  *              Walk_state      - Current method state
  297.  *
  298.  * RETURN:      Status
  299.  *
  300.  * DESCRIPTION: Convert an ACPI Object to a string
  301.  *
  302.  ******************************************************************************/
  303. acpi_status
  304. acpi_ex_convert_to_string (
  305. acpi_operand_object     *obj_desc,
  306. acpi_operand_object     **result_desc,
  307. u32                     base,
  308. u32                     max_length,
  309. acpi_walk_state         *walk_state)
  310. {
  311. acpi_operand_object     *ret_desc;
  312. u32                     i;
  313. u32                     index;
  314. u32                     string_length;
  315. u32                     integer_size = sizeof (acpi_integer);
  316. u8                      *new_buf;
  317. u8                      *pointer;
  318. FUNCTION_ENTRY ();
  319. switch (obj_desc->common.type) {
  320. case ACPI_TYPE_INTEGER:
  321. /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
  322. if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
  323. /*
  324.  * We are running a method that exists in a 32-bit ACPI table.
  325.  * Truncate the value to 32 bits by zeroing out the upper
  326.  * 32-bit field
  327.  */
  328. integer_size = sizeof (u32);
  329. }
  330. string_length = integer_size * 2;
  331. if (base == 10) {
  332. string_length = ACPI_MAX_DECIMAL_DIGITS;
  333. }
  334. /*
  335.  * Create a new String
  336.  */
  337. ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
  338. if (!ret_desc) {
  339. return (AE_NO_MEMORY);
  340. }
  341. /* Need enough space for one ASCII integer plus null terminator */
  342. new_buf = ACPI_MEM_CALLOCATE (string_length + 1);
  343. if (!new_buf) {
  344. REPORT_ERROR
  345. (("Ex_convert_to_string: Buffer allocation failuren"));
  346. acpi_ut_remove_reference (ret_desc);
  347. return (AE_NO_MEMORY);
  348. }
  349. /* Convert */
  350. i = acpi_ex_convert_to_ascii (obj_desc->integer.value, base, new_buf);
  351. /* Null terminate at the correct place */
  352. if (max_length < i) {
  353. new_buf[max_length] = 0;
  354. ret_desc->string.length = max_length;
  355. }
  356. else {
  357. new_buf [i] = 0;
  358. ret_desc->string.length = i;
  359. }
  360. ret_desc->buffer.pointer = new_buf;
  361. /* Return the new buffer descriptor */
  362. if (*result_desc == obj_desc) {
  363. if (walk_state->opcode != AML_STORE_OP) {
  364. acpi_ut_remove_reference (obj_desc);
  365. }
  366. }
  367. *result_desc = ret_desc;
  368. break;
  369. case ACPI_TYPE_BUFFER:
  370. string_length = obj_desc->buffer.length * 3;
  371. if (base == 10) {
  372. string_length = obj_desc->buffer.length * 4;
  373. }
  374. if (max_length > ACPI_MAX_STRING_CONVERSION) {
  375. if (string_length > ACPI_MAX_STRING_CONVERSION) {
  376. return (AE_AML_STRING_LIMIT);
  377. }
  378. }
  379. /*
  380.  * Create a new string object
  381.  */
  382. ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
  383. if (!ret_desc) {
  384. return (AE_NO_MEMORY);
  385. }
  386. /* String length is the lesser of the Max or the actual length */
  387. if (max_length < string_length) {
  388. string_length = max_length;
  389. }
  390. new_buf = ACPI_MEM_CALLOCATE (string_length + 1);
  391. if (!new_buf) {
  392. REPORT_ERROR
  393. (("Ex_convert_to_string: Buffer allocation failuren"));
  394. acpi_ut_remove_reference (ret_desc);
  395. return (AE_NO_MEMORY);
  396. }
  397. /*
  398.  * Convert each byte of the buffer to two ASCII characters plus a space.
  399.  */
  400. pointer = obj_desc->buffer.pointer;
  401. index = 0;
  402. for (i = 0, index = 0; i < obj_desc->buffer.length; i++) {
  403. index = acpi_ex_convert_to_ascii (pointer[i], base, &new_buf[index]);
  404. new_buf[index] = ' ';
  405. index++;
  406. }
  407. /* Null terminate */
  408. new_buf [index-1] = 0;
  409. ret_desc->buffer.pointer = new_buf;
  410. ret_desc->string.length = STRLEN ((char *) new_buf);
  411. /* Return the new buffer descriptor */
  412. if (*result_desc == obj_desc) {
  413. if (walk_state->opcode != AML_STORE_OP) {
  414. acpi_ut_remove_reference (obj_desc);
  415. }
  416. }
  417. *result_desc = ret_desc;
  418. break;
  419. case ACPI_TYPE_STRING:
  420. if (max_length >= obj_desc->string.length) {
  421. *result_desc = obj_desc;
  422. }
  423. else {
  424. /* Must copy the string first and then truncate it */
  425. return (AE_NOT_IMPLEMENTED);
  426. }
  427. break;
  428. default:
  429. return (AE_TYPE);
  430. break;
  431.    }
  432. return (AE_OK);
  433. }
  434. /*******************************************************************************
  435.  *
  436.  * FUNCTION:    Acpi_ex_convert_to_target_type
  437.  *
  438.  * PARAMETERS:  *Obj_desc       - Object to be converted.
  439.  *              Walk_state      - Current method state
  440.  *
  441.  * RETURN:      Status
  442.  *
  443.  * DESCRIPTION:
  444.  *
  445.  ******************************************************************************/
  446. acpi_status
  447. acpi_ex_convert_to_target_type (
  448. acpi_object_type8       destination_type,
  449. acpi_operand_object     **obj_desc,
  450. acpi_walk_state         *walk_state)
  451. {
  452. acpi_status             status = AE_OK;
  453. FUNCTION_TRACE ("Ex_convert_to_target_type");
  454. /*
  455.  * If required by the target,
  456.  * perform implicit conversion on the source before we store it.
  457.  */
  458. switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) {
  459. case ARGI_SIMPLE_TARGET:
  460. case ARGI_FIXED_TARGET:
  461. case ARGI_INTEGER_REF:      /* Handles Increment, Decrement cases */
  462. switch (destination_type) {
  463. case INTERNAL_TYPE_REGION_FIELD:
  464. /*
  465.  * Named field can always handle conversions
  466.  */
  467. break;
  468. default:
  469. /* No conversion allowed for these types */
  470. if (destination_type != (*obj_desc)->common.type) {
  471. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  472. "Target does not allow conversion of type %s to %sn",
  473. acpi_ut_get_type_name ((*obj_desc)->common.type),
  474. acpi_ut_get_type_name (destination_type)));
  475. status = AE_TYPE;
  476. }
  477. }
  478. break;
  479. case ARGI_TARGETREF:
  480. switch (destination_type) {
  481. case ACPI_TYPE_INTEGER:
  482. case ACPI_TYPE_BUFFER_FIELD:
  483. case INTERNAL_TYPE_BANK_FIELD:
  484. case INTERNAL_TYPE_INDEX_FIELD:
  485. /*
  486.  * These types require an Integer operand.  We can convert
  487.  * a Buffer or a String to an Integer if necessary.
  488.  */
  489. status = acpi_ex_convert_to_integer (*obj_desc, obj_desc, walk_state);
  490. break;
  491. case ACPI_TYPE_STRING:
  492. /*
  493.  * The operand must be a String.  We can convert an
  494.  * Integer or Buffer if necessary
  495.  */
  496. status = acpi_ex_convert_to_string (*obj_desc, obj_desc, 16, ACPI_UINT32_MAX, walk_state);
  497. break;
  498. case ACPI_TYPE_BUFFER:
  499. /*
  500.  * The operand must be a String.  We can convert an
  501.  * Integer or Buffer if necessary
  502.  */
  503. status = acpi_ex_convert_to_buffer (*obj_desc, obj_desc, walk_state);
  504. break;
  505. }
  506. break;
  507. case ARGI_REFERENCE:
  508. /*
  509.  * Create_xxxx_field cases - we are storing the field object into the name
  510.  */
  511. break;
  512. default:
  513. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  514. "Unknown Target type ID 0x%X Op %s Dest_type %sn",
  515. GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args),
  516. walk_state->op_info->name, acpi_ut_get_type_name (destination_type)));
  517. status = AE_AML_INTERNAL;
  518. }
  519. /*
  520.  * Source-to-Target conversion semantics:
  521.  *
  522.  * If conversion to the target type cannot be performed, then simply
  523.  * overwrite the target with the new object and type.
  524.  */
  525. if (status == AE_TYPE) {
  526. status = AE_OK;
  527. }
  528. return_ACPI_STATUS (status);
  529. }