rscalc.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. /*******************************************************************************
  2. *
  3. * Module Name: rscalc - Calculate stream and list lengths
  4. *
  5. ******************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2005, R. Byron Moore
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. #include <acpi/acpi.h>
  43. #include <acpi/acresrc.h>
  44. #include <acpi/amlcode.h>
  45. #include <acpi/acnamesp.h>
  46. #define _COMPONENT ACPI_RESOURCES
  47. ACPI_MODULE_NAME ("rscalc")
  48. /*******************************************************************************
  49. *
  50. * FUNCTION: acpi_rs_get_byte_stream_length
  51. *
  52. * PARAMETERS: linked_list - Pointer to the resource linked list
  53. * size_needed - u32 pointer of the size buffer needed
  54. * to properly return the parsed data
  55. *
  56. * RETURN: Status
  57. *
  58. * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
  59. * the size buffer needed to hold the linked list that conveys
  60. * the resource data.
  61. *
  62. ******************************************************************************/
  63. acpi_status
  64. acpi_rs_get_byte_stream_length (
  65. struct acpi_resource *linked_list,
  66. acpi_size *size_needed)
  67. {
  68. acpi_size byte_stream_size_needed = 0;
  69. acpi_size segment_size;
  70. u8 done = FALSE;
  71. ACPI_FUNCTION_TRACE ("rs_get_byte_stream_length");
  72. while (!done) {
  73. /* Init the variable that will hold the size to add to the total. */
  74. segment_size = 0;
  75. switch (linked_list->id) {
  76. case ACPI_RSTYPE_IRQ:
  77. /*
  78. * IRQ Resource
  79. * For an IRQ Resource, Byte 3, although optional, will always be
  80. * created - it holds IRQ information.
  81. */
  82. segment_size = 4;
  83. break;
  84. case ACPI_RSTYPE_DMA:
  85. /*
  86. * DMA Resource
  87. * For this resource the size is static
  88. */
  89. segment_size = 3;
  90. break;
  91. case ACPI_RSTYPE_START_DPF:
  92. /*
  93. * Start Dependent Functions Resource
  94. * For a start_dependent_functions Resource, Byte 1, although
  95. * optional, will always be created.
  96. */
  97. segment_size = 2;
  98. break;
  99. case ACPI_RSTYPE_END_DPF:
  100. /*
  101. * End Dependent Functions Resource
  102. * For this resource the size is static
  103. */
  104. segment_size = 1;
  105. break;
  106. case ACPI_RSTYPE_IO:
  107. /*
  108. * IO Port Resource
  109. * For this resource the size is static
  110. */
  111. segment_size = 8;
  112. break;
  113. case ACPI_RSTYPE_FIXED_IO:
  114. /*
  115. * Fixed IO Port Resource
  116. * For this resource the size is static
  117. */
  118. segment_size = 4;
  119. break;
  120. case ACPI_RSTYPE_VENDOR:
  121. /*
  122. * Vendor Defined Resource
  123. * For a Vendor Specific resource, if the Length is between 1 and 7
  124. * it will be created as a Small Resource data type, otherwise it
  125. * is a Large Resource data type.
  126. */
  127. if (linked_list->data.vendor_specific.length > 7) {
  128. segment_size = 3;
  129. }
  130. else {
  131. segment_size = 1;
  132. }
  133. segment_size += linked_list->data.vendor_specific.length;
  134. break;
  135. case ACPI_RSTYPE_END_TAG:
  136. /*
  137. * End Tag
  138. * For this resource the size is static
  139. */
  140. segment_size = 2;
  141. done = TRUE;
  142. break;
  143. case ACPI_RSTYPE_MEM24:
  144. /*
  145. * 24-Bit Memory Resource
  146. * For this resource the size is static
  147. */
  148. segment_size = 12;
  149. break;
  150. case ACPI_RSTYPE_MEM32:
  151. /*
  152. * 32-Bit Memory Range Resource
  153. * For this resource the size is static
  154. */
  155. segment_size = 20;
  156. break;
  157. case ACPI_RSTYPE_FIXED_MEM32:
  158. /*
  159. * 32-Bit Fixed Memory Resource
  160. * For this resource the size is static
  161. */
  162. segment_size = 12;
  163. break;
  164. case ACPI_RSTYPE_ADDRESS16:
  165. /*
  166. * 16-Bit Address Resource
  167. * The base size of this byte stream is 16. If a Resource Source
  168. * string is not NULL, add 1 for the Index + the length of the null
  169. * terminated string Resource Source + 1 for the null.
  170. */
  171. segment_size = 16;
  172. if (linked_list->data.address16.resource_source.string_ptr) {
  173. segment_size +=
  174. linked_list->data.address16.resource_source.string_length;
  175. segment_size++;
  176. }
  177. break;
  178. case ACPI_RSTYPE_ADDRESS32:
  179. /*
  180. * 32-Bit Address Resource
  181. * The base size of this byte stream is 26. If a Resource
  182. * Source string is not NULL, add 1 for the Index + the
  183. * length of the null terminated string Resource Source +
  184. * 1 for the null.
  185. */
  186. segment_size = 26;
  187. if (linked_list->data.address32.resource_source.string_ptr) {
  188. segment_size +=
  189. linked_list->data.address32.resource_source.string_length;
  190. segment_size++;
  191. }
  192. break;
  193. case ACPI_RSTYPE_ADDRESS64:
  194. /*
  195. * 64-Bit Address Resource
  196. * The base size of this byte stream is 46. If a resource_source
  197. * string is not NULL, add 1 for the Index + the length of the null
  198. * terminated string Resource Source + 1 for the null.
  199. */
  200. segment_size = 46;
  201. if (linked_list->data.address64.resource_source.string_ptr) {
  202. segment_size +=
  203. linked_list->data.address64.resource_source.string_length;
  204. segment_size++;
  205. }
  206. break;
  207. case ACPI_RSTYPE_EXT_IRQ:
  208. /*
  209. * Extended IRQ Resource
  210. * The base size of this byte stream is 9. This is for an Interrupt
  211. * table length of 1. For each additional interrupt, add 4.
  212. * If a Resource Source string is not NULL, add 1 for the
  213. * Index + the length of the null terminated string
  214. * Resource Source + 1 for the null.
  215. */
  216. segment_size = 9 + (((acpi_size)
  217. linked_list->data.extended_irq.number_of_interrupts - 1) * 4);
  218. if (linked_list->data.extended_irq.resource_source.string_ptr) {
  219. segment_size +=
  220. linked_list->data.extended_irq.resource_source.string_length;
  221. segment_size++;
  222. }
  223. break;
  224. default:
  225. /* If we get here, everything is out of sync, exit with error */
  226. return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
  227. } /* switch (linked_list->Id) */
  228. /* Update the total */
  229. byte_stream_size_needed += segment_size;
  230. /* Point to the next object */
  231. linked_list = ACPI_PTR_ADD (struct acpi_resource,
  232. linked_list, linked_list->length);
  233. }
  234. /* This is the data the caller needs */
  235. *size_needed = byte_stream_size_needed;
  236. return_ACPI_STATUS (AE_OK);
  237. }
  238. /*******************************************************************************
  239. *
  240. * FUNCTION: acpi_rs_get_list_length
  241. *
  242. * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream
  243. * byte_stream_buffer_length - Size of byte_stream_buffer
  244. * size_needed - u32 pointer of the size buffer
  245. * needed to properly return the
  246. * parsed data
  247. *
  248. * RETURN: Status
  249. *
  250. * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
  251. * the size buffer needed to hold the linked list that conveys
  252. * the resource data.
  253. *
  254. ******************************************************************************/
  255. acpi_status
  256. acpi_rs_get_list_length (
  257. u8 *byte_stream_buffer,
  258. u32 byte_stream_buffer_length,
  259. acpi_size *size_needed)
  260. {
  261. u32 buffer_size = 0;
  262. u32 bytes_parsed = 0;
  263. u8 number_of_interrupts = 0;
  264. u8 number_of_channels = 0;
  265. u8 resource_type;
  266. u32 structure_size;
  267. u32 bytes_consumed;
  268. u8 *buffer;
  269. u8 temp8;
  270. u16 temp16;
  271. u8 index;
  272. u8 additional_bytes;
  273. ACPI_FUNCTION_TRACE ("rs_get_list_length");
  274. while (bytes_parsed < byte_stream_buffer_length) {
  275. /* The next byte in the stream is the resource type */
  276. resource_type = acpi_rs_get_resource_type (*byte_stream_buffer);
  277. switch (resource_type) {
  278. case ACPI_RDESC_TYPE_MEMORY_24:
  279. /*
  280. * 24-Bit Memory Resource
  281. */
  282. bytes_consumed = 12;
  283. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem24);
  284. break;
  285. case ACPI_RDESC_TYPE_LARGE_VENDOR:
  286. /*
  287. * Vendor Defined Resource
  288. */
  289. buffer = byte_stream_buffer;
  290. ++buffer;
  291. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  292. bytes_consumed = temp16 + 3;
  293. /* Ensure a 32-bit boundary for the structure */
  294. temp16 = (u16) ACPI_ROUND_UP_to_32_bITS (temp16);
  295. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
  296. (temp16 * sizeof (u8));
  297. break;
  298. case ACPI_RDESC_TYPE_MEMORY_32:
  299. /*
  300. * 32-Bit Memory Range Resource
  301. */
  302. bytes_consumed = 20;
  303. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32);
  304. break;
  305. case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
  306. /*
  307. * 32-Bit Fixed Memory Resource
  308. */
  309. bytes_consumed = 12;
  310. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_mem32);
  311. break;
  312. case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
  313. /*
  314. * 64-Bit Address Resource
  315. */
  316. buffer = byte_stream_buffer;
  317. ++buffer;
  318. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  319. bytes_consumed = temp16 + 3;
  320. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
  321. break;
  322. case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
  323. /*
  324. * 64-Bit Address Resource
  325. */
  326. buffer = byte_stream_buffer;
  327. ++buffer;
  328. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  329. bytes_consumed = temp16 + 3;
  330. /*
  331. * Resource Source Index and Resource Source are optional elements.
  332. * Check the length of the Bytestream. If it is greater than 43,
  333. * that means that an Index exists and is followed by a null
  334. * terminated string. Therefore, set the temp variable to the
  335. * length minus the minimum byte stream length plus the byte for
  336. * the Index to determine the size of the NULL terminated string.
  337. */
  338. if (43 < temp16) {
  339. temp8 = (u8) (temp16 - 44);
  340. }
  341. else {
  342. temp8 = 0;
  343. }
  344. /* Ensure a 64-bit boundary for the structure */
  345. temp8 = (u8) ACPI_ROUND_UP_to_64_bITS (temp8);
  346. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64) +
  347. (temp8 * sizeof (u8));
  348. break;
  349. case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
  350. /*
  351. * 32-Bit Address Resource
  352. */
  353. buffer = byte_stream_buffer;
  354. ++buffer;
  355. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  356. bytes_consumed = temp16 + 3;
  357. /*
  358. * Resource Source Index and Resource Source are optional elements.
  359. * Check the length of the Bytestream. If it is greater than 23,
  360. * that means that an Index exists and is followed by a null
  361. * terminated string. Therefore, set the temp variable to the
  362. * length minus the minimum byte stream length plus the byte for
  363. * the Index to determine the size of the NULL terminated string.
  364. */
  365. if (23 < temp16) {
  366. temp8 = (u8) (temp16 - 24);
  367. }
  368. else {
  369. temp8 = 0;
  370. }
  371. /* Ensure a 32-bit boundary for the structure */
  372. temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
  373. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32) +
  374. (temp8 * sizeof (u8));
  375. break;
  376. case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
  377. /*
  378. * 16-Bit Address Resource
  379. */
  380. buffer = byte_stream_buffer;
  381. ++buffer;
  382. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  383. bytes_consumed = temp16 + 3;
  384. /*
  385. * Resource Source Index and Resource Source are optional elements.
  386. * Check the length of the Bytestream. If it is greater than 13,
  387. * that means that an Index exists and is followed by a null
  388. * terminated string. Therefore, set the temp variable to the
  389. * length minus the minimum byte stream length plus the byte for
  390. * the Index to determine the size of the NULL terminated string.
  391. */
  392. if (13 < temp16) {
  393. temp8 = (u8) (temp16 - 14);
  394. }
  395. else {
  396. temp8 = 0;
  397. }
  398. /* Ensure a 32-bit boundary for the structure */
  399. temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
  400. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16) +
  401. (temp8 * sizeof (u8));
  402. break;
  403. case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
  404. /*
  405. * Extended IRQ
  406. */
  407. buffer = byte_stream_buffer;
  408. ++buffer;
  409. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  410. bytes_consumed = temp16 + 3;
  411. /*
  412. * Point past the length field and the Interrupt vector flags to
  413. * save off the Interrupt table length to the Temp8 variable.
  414. */
  415. buffer += 3;
  416. temp8 = *buffer;
  417. /*
  418. * To compensate for multiple interrupt numbers, add 4 bytes for
  419. * each additional interrupts greater than 1
  420. */
  421. additional_bytes = (u8) ((temp8 - 1) * 4);
  422. /*
  423. * Resource Source Index and Resource Source are optional elements.
  424. * Check the length of the Bytestream. If it is greater than 9,
  425. * that means that an Index exists and is followed by a null
  426. * terminated string. Therefore, set the temp variable to the
  427. * length minus the minimum byte stream length plus the byte for
  428. * the Index to determine the size of the NULL terminated string.
  429. */
  430. if (9 + additional_bytes < temp16) {
  431. temp8 = (u8) (temp16 - (9 + additional_bytes));
  432. }
  433. else {
  434. temp8 = 0;
  435. }
  436. /* Ensure a 32-bit boundary for the structure */
  437. temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
  438. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_ext_irq) +
  439. (additional_bytes * sizeof (u8)) +
  440. (temp8 * sizeof (u8));
  441. break;
  442. case ACPI_RDESC_TYPE_IRQ_FORMAT:
  443. /*
  444. * IRQ Resource.
  445. * Determine if it there are two or three trailing bytes
  446. */
  447. buffer = byte_stream_buffer;
  448. temp8 = *buffer;
  449. if(temp8 & 0x01) {
  450. bytes_consumed = 4;
  451. }
  452. else {
  453. bytes_consumed = 3;
  454. }
  455. /* Point past the descriptor */
  456. ++buffer;
  457. /* Look at the number of bits set */
  458. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  459. for (index = 0; index < 16; index++) {
  460. if (temp16 & 0x1) {
  461. ++number_of_interrupts;
  462. }
  463. temp16 >>= 1;
  464. }
  465. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io) +
  466. (number_of_interrupts * sizeof (u32));
  467. break;
  468. case ACPI_RDESC_TYPE_DMA_FORMAT:
  469. /*
  470. * DMA Resource
  471. */
  472. buffer = byte_stream_buffer;
  473. bytes_consumed = 3;
  474. /* Point past the descriptor */
  475. ++buffer;
  476. /* Look at the number of bits set */
  477. temp8 = *buffer;
  478. for(index = 0; index < 8; index++) {
  479. if(temp8 & 0x1) {
  480. ++number_of_channels;
  481. }
  482. temp8 >>= 1;
  483. }
  484. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_dma) +
  485. (number_of_channels * sizeof (u32));
  486. break;
  487. case ACPI_RDESC_TYPE_START_DEPENDENT:
  488. /*
  489. * Start Dependent Functions Resource
  490. * Determine if it there are two or three trailing bytes
  491. */
  492. buffer = byte_stream_buffer;
  493. temp8 = *buffer;
  494. if(temp8 & 0x01) {
  495. bytes_consumed = 2;
  496. }
  497. else {
  498. bytes_consumed = 1;
  499. }
  500. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_start_dpf);
  501. break;
  502. case ACPI_RDESC_TYPE_END_DEPENDENT:
  503. /*
  504. * End Dependent Functions Resource
  505. */
  506. bytes_consumed = 1;
  507. structure_size = ACPI_RESOURCE_LENGTH;
  508. break;
  509. case ACPI_RDESC_TYPE_IO_PORT:
  510. /*
  511. * IO Port Resource
  512. */
  513. bytes_consumed = 8;
  514. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io);
  515. break;
  516. case ACPI_RDESC_TYPE_FIXED_IO_PORT:
  517. /*
  518. * Fixed IO Port Resource
  519. */
  520. bytes_consumed = 4;
  521. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_io);
  522. break;
  523. case ACPI_RDESC_TYPE_SMALL_VENDOR:
  524. /*
  525. * Vendor Specific Resource
  526. */
  527. buffer = byte_stream_buffer;
  528. temp8 = *buffer;
  529. temp8 = (u8) (temp8 & 0x7);
  530. bytes_consumed = temp8 + 1;
  531. /* Ensure a 32-bit boundary for the structure */
  532. temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
  533. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
  534. (temp8 * sizeof (u8));
  535. break;
  536. case ACPI_RDESC_TYPE_END_TAG:
  537. /*
  538. * End Tag
  539. */
  540. bytes_consumed = 2;
  541. structure_size = ACPI_RESOURCE_LENGTH;
  542. byte_stream_buffer_length = bytes_parsed;
  543. break;
  544. default:
  545. /*
  546. * If we get here, everything is out of sync,
  547. * exit with an error
  548. */
  549. return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
  550. }
  551. /* Update the return value and counter */
  552. buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE (structure_size);
  553. bytes_parsed += bytes_consumed;
  554. /* Set the byte stream to point to the next resource */
  555. byte_stream_buffer += bytes_consumed;
  556. }
  557. /* This is the data the caller needs */
  558. *size_needed = buffer_size;
  559. return_ACPI_STATUS (AE_OK);
  560. }
  561. /*******************************************************************************
  562. *
  563. * FUNCTION: acpi_rs_get_pci_routing_table_length
  564. *
  565. * PARAMETERS: package_object - Pointer to the package object
  566. * buffer_size_needed - u32 pointer of the size buffer
  567. * needed to properly return the
  568. * parsed data
  569. *
  570. * RETURN: Status
  571. *
  572. * DESCRIPTION: Given a package representing a PCI routing table, this
  573. * calculates the size of the corresponding linked list of
  574. * descriptions.
  575. *
  576. ******************************************************************************/
  577. acpi_status
  578. acpi_rs_get_pci_routing_table_length (
  579. union acpi_operand_object *package_object,
  580. acpi_size *buffer_size_needed)
  581. {
  582. u32 number_of_elements;
  583. acpi_size temp_size_needed = 0;
  584. union acpi_operand_object **top_object_list;
  585. u32 index;
  586. union acpi_operand_object *package_element;
  587. union acpi_operand_object **sub_object_list;
  588. u8 name_found;
  589. u32 table_index;
  590. ACPI_FUNCTION_TRACE ("rs_get_pci_routing_table_length");
  591. number_of_elements = package_object->package.count;
  592. /*
  593. * Calculate the size of the return buffer.
  594. * The base size is the number of elements * the sizes of the
  595. * structures. Additional space for the strings is added below.
  596. * The minus one is to subtract the size of the u8 Source[1]
  597. * member because it is added below.
  598. *
  599. * But each PRT_ENTRY structure has a pointer to a string and
  600. * the size of that string must be found.
  601. */
  602. top_object_list = package_object->package.elements;
  603. for (index = 0; index < number_of_elements; index++) {
  604. /* Dereference the sub-package */
  605. package_element = *top_object_list;
  606. /*
  607. * The sub_object_list will now point to an array of the
  608. * four IRQ elements: Address, Pin, Source and source_index
  609. */
  610. sub_object_list = package_element->package.elements;
  611. /* Scan the irq_table_elements for the Source Name String */
  612. name_found = FALSE;
  613. for (table_index = 0; table_index < 4 && !name_found; table_index++) {
  614. if ((ACPI_TYPE_STRING ==
  615. ACPI_GET_OBJECT_TYPE (*sub_object_list)) ||
  616. ((ACPI_TYPE_LOCAL_REFERENCE ==
  617. ACPI_GET_OBJECT_TYPE (*sub_object_list)) &&
  618. ((*sub_object_list)->reference.opcode ==
  619. AML_INT_NAMEPATH_OP))) {
  620. name_found = TRUE;
  621. }
  622. else {
  623. /* Look at the next element */
  624. sub_object_list++;
  625. }
  626. }
  627. temp_size_needed += (sizeof (struct acpi_pci_routing_table) - 4);
  628. /* Was a String type found? */
  629. if (name_found) {
  630. if (ACPI_GET_OBJECT_TYPE (*sub_object_list) == ACPI_TYPE_STRING) {
  631. /*
  632. * The length String.Length field does not include the
  633. * terminating NULL, add 1
  634. */
  635. temp_size_needed += ((acpi_size)
  636. (*sub_object_list)->string.length + 1);
  637. }
  638. else {
  639. temp_size_needed += acpi_ns_get_pathname_length (
  640. (*sub_object_list)->reference.node);
  641. }
  642. }
  643. else {
  644. /*
  645. * If no name was found, then this is a NULL, which is
  646. * translated as a u32 zero.
  647. */
  648. temp_size_needed += sizeof (u32);
  649. }
  650. /* Round up the size since each element must be aligned */
  651. temp_size_needed = ACPI_ROUND_UP_to_64_bITS (temp_size_needed);
  652. /* Point to the next union acpi_operand_object */
  653. top_object_list++;
  654. }
  655. /*
  656. * Adding an extra element to the end of the list, essentially a
  657. * NULL terminator
  658. */
  659. *buffer_size_needed = temp_size_needed + sizeof (struct acpi_pci_routing_table);
  660. return_ACPI_STATUS (AE_OK);
  661. }