rscalc.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  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. /*
  74. * Init the variable that will hold the size to add to the total.
  75. */
  76. segment_size = 0;
  77. switch (linked_list->id) {
  78. case ACPI_RSTYPE_IRQ:
  79. /*
  80. * IRQ Resource
  81. * For an IRQ Resource, Byte 3, although optional, will always be
  82. * created - it holds IRQ information.
  83. */
  84. segment_size = 4;
  85. break;
  86. case ACPI_RSTYPE_DMA:
  87. /*
  88. * DMA Resource
  89. * For this resource the size is static
  90. */
  91. segment_size = 3;
  92. break;
  93. case ACPI_RSTYPE_START_DPF:
  94. /*
  95. * Start Dependent Functions Resource
  96. * For a start_dependent_functions Resource, Byte 1, although
  97. * optional, will always be created.
  98. */
  99. segment_size = 2;
  100. break;
  101. case ACPI_RSTYPE_END_DPF:
  102. /*
  103. * End Dependent Functions Resource
  104. * For this resource the size is static
  105. */
  106. segment_size = 1;
  107. break;
  108. case ACPI_RSTYPE_IO:
  109. /*
  110. * IO Port Resource
  111. * For this resource the size is static
  112. */
  113. segment_size = 8;
  114. break;
  115. case ACPI_RSTYPE_FIXED_IO:
  116. /*
  117. * Fixed IO Port Resource
  118. * For this resource the size is static
  119. */
  120. segment_size = 4;
  121. break;
  122. case ACPI_RSTYPE_VENDOR:
  123. /*
  124. * Vendor Defined Resource
  125. * For a Vendor Specific resource, if the Length is between 1 and 7
  126. * it will be created as a Small Resource data type, otherwise it
  127. * is a Large Resource data type.
  128. */
  129. if (linked_list->data.vendor_specific.length > 7) {
  130. segment_size = 3;
  131. }
  132. else {
  133. segment_size = 1;
  134. }
  135. segment_size += linked_list->data.vendor_specific.length;
  136. break;
  137. case ACPI_RSTYPE_END_TAG:
  138. /*
  139. * End Tag
  140. * For this resource the size is static
  141. */
  142. segment_size = 2;
  143. done = TRUE;
  144. break;
  145. case ACPI_RSTYPE_MEM24:
  146. /*
  147. * 24-Bit Memory Resource
  148. * For this resource the size is static
  149. */
  150. segment_size = 12;
  151. break;
  152. case ACPI_RSTYPE_MEM32:
  153. /*
  154. * 32-Bit Memory Range Resource
  155. * For this resource the size is static
  156. */
  157. segment_size = 20;
  158. break;
  159. case ACPI_RSTYPE_FIXED_MEM32:
  160. /*
  161. * 32-Bit Fixed Memory Resource
  162. * For this resource the size is static
  163. */
  164. segment_size = 12;
  165. break;
  166. case ACPI_RSTYPE_ADDRESS16:
  167. /*
  168. * 16-Bit Address Resource
  169. * The base size of this byte stream is 16. If a Resource Source
  170. * string is not NULL, add 1 for the Index + the length of the null
  171. * terminated string Resource Source + 1 for the null.
  172. */
  173. segment_size = 16;
  174. if (linked_list->data.address16.resource_source.string_ptr) {
  175. segment_size += linked_list->data.address16.resource_source.string_length;
  176. segment_size++;
  177. }
  178. break;
  179. case ACPI_RSTYPE_ADDRESS32:
  180. /*
  181. * 32-Bit Address Resource
  182. * The base size of this byte stream is 26. If a Resource
  183. * Source string is not NULL, add 1 for the Index + the
  184. * length of the null terminated string Resource Source +
  185. * 1 for the null.
  186. */
  187. segment_size = 26;
  188. if (linked_list->data.address32.resource_source.string_ptr) {
  189. segment_size += 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 += linked_list->data.address64.resource_source.string_length;
  203. segment_size++;
  204. }
  205. break;
  206. case ACPI_RSTYPE_EXT_IRQ:
  207. /*
  208. * Extended IRQ Resource
  209. * The base size of this byte stream is 9. This is for an Interrupt
  210. * table length of 1. For each additional interrupt, add 4.
  211. * If a Resource Source string is not NULL, add 1 for the
  212. * Index + the length of the null terminated string
  213. * Resource Source + 1 for the null.
  214. */
  215. segment_size = 9 +
  216. (((acpi_size) linked_list->data.extended_irq.number_of_interrupts - 1) * 4);
  217. if (linked_list->data.extended_irq.resource_source.string_ptr) {
  218. segment_size += linked_list->data.extended_irq.resource_source.string_length;
  219. segment_size++;
  220. }
  221. break;
  222. default:
  223. /*
  224. * If we get here, everything is out of sync, exit with error
  225. */
  226. return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
  227. } /* switch (linked_list->Id) */
  228. /*
  229. * Update the total
  230. */
  231. byte_stream_size_needed += segment_size;
  232. /*
  233. * Point to the next object
  234. */
  235. linked_list = ACPI_PTR_ADD (struct acpi_resource,
  236. linked_list, linked_list->length);
  237. }
  238. /*
  239. * This is the data the caller needs
  240. */
  241. *size_needed = byte_stream_size_needed;
  242. return_ACPI_STATUS (AE_OK);
  243. }
  244. /*******************************************************************************
  245. *
  246. * FUNCTION: acpi_rs_get_list_length
  247. *
  248. * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream
  249. * byte_stream_buffer_length - Size of byte_stream_buffer
  250. * size_needed - u32 pointer of the size buffer
  251. * needed to properly return the
  252. * parsed data
  253. *
  254. * RETURN: Status
  255. *
  256. * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
  257. * the size buffer needed to hold the linked list that conveys
  258. * the resource data.
  259. *
  260. ******************************************************************************/
  261. acpi_status
  262. acpi_rs_get_list_length (
  263. u8 *byte_stream_buffer,
  264. u32 byte_stream_buffer_length,
  265. acpi_size *size_needed)
  266. {
  267. u32 buffer_size = 0;
  268. u32 bytes_parsed = 0;
  269. u8 number_of_interrupts = 0;
  270. u8 number_of_channels = 0;
  271. u8 resource_type;
  272. u32 structure_size;
  273. u32 bytes_consumed;
  274. u8 *buffer;
  275. u8 temp8;
  276. u16 temp16;
  277. u8 index;
  278. u8 additional_bytes;
  279. ACPI_FUNCTION_TRACE ("rs_get_list_length");
  280. while (bytes_parsed < byte_stream_buffer_length) {
  281. /*
  282. * The next byte in the stream is the resource type
  283. */
  284. resource_type = acpi_rs_get_resource_type (*byte_stream_buffer);
  285. switch (resource_type) {
  286. case ACPI_RDESC_TYPE_MEMORY_24:
  287. /*
  288. * 24-Bit Memory Resource
  289. */
  290. bytes_consumed = 12;
  291. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem24);
  292. break;
  293. case ACPI_RDESC_TYPE_LARGE_VENDOR:
  294. /*
  295. * Vendor Defined Resource
  296. */
  297. buffer = byte_stream_buffer;
  298. ++buffer;
  299. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  300. bytes_consumed = temp16 + 3;
  301. /*
  302. * Ensure a 32-bit boundary for the structure
  303. */
  304. temp16 = (u16) ACPI_ROUND_UP_to_32_bITS (temp16);
  305. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
  306. (temp16 * sizeof (u8));
  307. break;
  308. case ACPI_RDESC_TYPE_MEMORY_32:
  309. /*
  310. * 32-Bit Memory Range Resource
  311. */
  312. bytes_consumed = 20;
  313. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32);
  314. break;
  315. case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
  316. /*
  317. * 32-Bit Fixed Memory Resource
  318. */
  319. bytes_consumed = 12;
  320. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_mem32);
  321. break;
  322. case ACPI_RDESC_TYPE_EXTENDED_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. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
  331. break;
  332. case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
  333. /*
  334. * 64-Bit Address Resource
  335. */
  336. buffer = byte_stream_buffer;
  337. ++buffer;
  338. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  339. bytes_consumed = temp16 + 3;
  340. /*
  341. * Resource Source Index and Resource Source are optional elements.
  342. * Check the length of the Bytestream. If it is greater than 43,
  343. * that means that an Index exists and is followed by a null
  344. * terminated string. Therefore, set the temp variable to the
  345. * length minus the minimum byte stream length plus the byte for
  346. * the Index to determine the size of the NULL terminated string.
  347. */
  348. if (43 < temp16) {
  349. temp8 = (u8) (temp16 - 44);
  350. }
  351. else {
  352. temp8 = 0;
  353. }
  354. /*
  355. * Ensure a 64-bit boundary for the structure
  356. */
  357. temp8 = (u8) ACPI_ROUND_UP_to_64_bITS (temp8);
  358. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64) +
  359. (temp8 * sizeof (u8));
  360. break;
  361. case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
  362. /*
  363. * 32-Bit Address Resource
  364. */
  365. buffer = byte_stream_buffer;
  366. ++buffer;
  367. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  368. bytes_consumed = temp16 + 3;
  369. /*
  370. * Resource Source Index and Resource Source are optional elements.
  371. * Check the length of the Bytestream. If it is greater than 23,
  372. * that means that an Index exists and is followed by a null
  373. * terminated string. Therefore, set the temp variable to the
  374. * length minus the minimum byte stream length plus the byte for
  375. * the Index to determine the size of the NULL terminated string.
  376. */
  377. if (23 < temp16) {
  378. temp8 = (u8) (temp16 - 24);
  379. }
  380. else {
  381. temp8 = 0;
  382. }
  383. /*
  384. * Ensure a 32-bit boundary for the structure
  385. */
  386. temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
  387. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32) +
  388. (temp8 * sizeof (u8));
  389. break;
  390. case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
  391. /*
  392. * 16-Bit Address Resource
  393. */
  394. buffer = byte_stream_buffer;
  395. ++buffer;
  396. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  397. bytes_consumed = temp16 + 3;
  398. /*
  399. * Resource Source Index and Resource Source are optional elements.
  400. * Check the length of the Bytestream. If it is greater than 13,
  401. * that means that an Index exists and is followed by a null
  402. * terminated string. Therefore, set the temp variable to the
  403. * length minus the minimum byte stream length plus the byte for
  404. * the Index to determine the size of the NULL terminated string.
  405. */
  406. if (13 < temp16) {
  407. temp8 = (u8) (temp16 - 14);
  408. }
  409. else {
  410. temp8 = 0;
  411. }
  412. /*
  413. * Ensure a 32-bit boundary for the structure
  414. */
  415. temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
  416. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16) +
  417. (temp8 * sizeof (u8));
  418. break;
  419. case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
  420. /*
  421. * Extended IRQ
  422. */
  423. buffer = byte_stream_buffer;
  424. ++buffer;
  425. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  426. bytes_consumed = temp16 + 3;
  427. /*
  428. * Point past the length field and the Interrupt vector flags to
  429. * save off the Interrupt table length to the Temp8 variable.
  430. */
  431. buffer += 3;
  432. temp8 = *buffer;
  433. /*
  434. * To compensate for multiple interrupt numbers, add 4 bytes for
  435. * each additional interrupts greater than 1
  436. */
  437. additional_bytes = (u8) ((temp8 - 1) * 4);
  438. /*
  439. * Resource Source Index and Resource Source are optional elements.
  440. * Check the length of the Bytestream. If it is greater than 9,
  441. * that means that an Index exists and is followed by a null
  442. * terminated string. Therefore, set the temp variable to the
  443. * length minus the minimum byte stream length plus the byte for
  444. * the Index to determine the size of the NULL terminated string.
  445. */
  446. if (9 + additional_bytes < temp16) {
  447. temp8 = (u8) (temp16 - (9 + additional_bytes));
  448. }
  449. else {
  450. temp8 = 0;
  451. }
  452. /*
  453. * Ensure a 32-bit boundary for the structure
  454. */
  455. temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
  456. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_ext_irq) +
  457. (additional_bytes * sizeof (u8)) +
  458. (temp8 * sizeof (u8));
  459. break;
  460. case ACPI_RDESC_TYPE_IRQ_FORMAT:
  461. /*
  462. * IRQ Resource.
  463. * Determine if it there are two or three trailing bytes
  464. */
  465. buffer = byte_stream_buffer;
  466. temp8 = *buffer;
  467. if(temp8 & 0x01) {
  468. bytes_consumed = 4;
  469. }
  470. else {
  471. bytes_consumed = 3;
  472. }
  473. /* Point past the descriptor */
  474. ++buffer;
  475. /*
  476. * Look at the number of bits set
  477. */
  478. ACPI_MOVE_16_TO_16 (&temp16, buffer);
  479. for (index = 0; index < 16; index++) {
  480. if (temp16 & 0x1) {
  481. ++number_of_interrupts;
  482. }
  483. temp16 >>= 1;
  484. }
  485. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io) +
  486. (number_of_interrupts * sizeof (u32));
  487. break;
  488. case ACPI_RDESC_TYPE_DMA_FORMAT:
  489. /*
  490. * DMA Resource
  491. */
  492. buffer = byte_stream_buffer;
  493. bytes_consumed = 3;
  494. /* Point past the descriptor */
  495. ++buffer;
  496. /*
  497. * Look at the number of bits set
  498. */
  499. temp8 = *buffer;
  500. for(index = 0; index < 8; index++) {
  501. if(temp8 & 0x1) {
  502. ++number_of_channels;
  503. }
  504. temp8 >>= 1;
  505. }
  506. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_dma) +
  507. (number_of_channels * sizeof (u32));
  508. break;
  509. case ACPI_RDESC_TYPE_START_DEPENDENT:
  510. /*
  511. * Start Dependent Functions Resource
  512. * Determine if it there are two or three trailing bytes
  513. */
  514. buffer = byte_stream_buffer;
  515. temp8 = *buffer;
  516. if(temp8 & 0x01) {
  517. bytes_consumed = 2;
  518. }
  519. else {
  520. bytes_consumed = 1;
  521. }
  522. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_start_dpf);
  523. break;
  524. case ACPI_RDESC_TYPE_END_DEPENDENT:
  525. /*
  526. * End Dependent Functions Resource
  527. */
  528. bytes_consumed = 1;
  529. structure_size = ACPI_RESOURCE_LENGTH;
  530. break;
  531. case ACPI_RDESC_TYPE_IO_PORT:
  532. /*
  533. * IO Port Resource
  534. */
  535. bytes_consumed = 8;
  536. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io);
  537. break;
  538. case ACPI_RDESC_TYPE_FIXED_IO_PORT:
  539. /*
  540. * Fixed IO Port Resource
  541. */
  542. bytes_consumed = 4;
  543. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_io);
  544. break;
  545. case ACPI_RDESC_TYPE_SMALL_VENDOR:
  546. /*
  547. * Vendor Specific Resource
  548. */
  549. buffer = byte_stream_buffer;
  550. temp8 = *buffer;
  551. temp8 = (u8) (temp8 & 0x7);
  552. bytes_consumed = temp8 + 1;
  553. /*
  554. * Ensure a 32-bit boundary for the structure
  555. */
  556. temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
  557. structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
  558. (temp8 * sizeof (u8));
  559. break;
  560. case ACPI_RDESC_TYPE_END_TAG:
  561. /*
  562. * End Tag
  563. */
  564. bytes_consumed = 2;
  565. structure_size = ACPI_RESOURCE_LENGTH;
  566. byte_stream_buffer_length = bytes_parsed;
  567. break;
  568. default:
  569. /*
  570. * If we get here, everything is out of sync,
  571. * exit with an error
  572. */
  573. return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
  574. }
  575. /*
  576. * Update the return value and counter
  577. */
  578. buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE (structure_size);
  579. bytes_parsed += bytes_consumed;
  580. /*
  581. * Set the byte stream to point to the next resource
  582. */
  583. byte_stream_buffer += bytes_consumed;
  584. }
  585. /*
  586. * This is the data the caller needs
  587. */
  588. *size_needed = buffer_size;
  589. return_ACPI_STATUS (AE_OK);
  590. }
  591. /*******************************************************************************
  592. *
  593. * FUNCTION: acpi_rs_get_pci_routing_table_length
  594. *
  595. * PARAMETERS: package_object - Pointer to the package object
  596. * buffer_size_needed - u32 pointer of the size buffer
  597. * needed to properly return the
  598. * parsed data
  599. *
  600. * RETURN: Status
  601. *
  602. * DESCRIPTION: Given a package representing a PCI routing table, this
  603. * calculates the size of the corresponding linked list of
  604. * descriptions.
  605. *
  606. ******************************************************************************/
  607. acpi_status
  608. acpi_rs_get_pci_routing_table_length (
  609. union acpi_operand_object *package_object,
  610. acpi_size *buffer_size_needed)
  611. {
  612. u32 number_of_elements;
  613. acpi_size temp_size_needed = 0;
  614. union acpi_operand_object **top_object_list;
  615. u32 index;
  616. union acpi_operand_object *package_element;
  617. union acpi_operand_object **sub_object_list;
  618. u8 name_found;
  619. u32 table_index;
  620. ACPI_FUNCTION_TRACE ("rs_get_pci_routing_table_length");
  621. number_of_elements = package_object->package.count;
  622. /*
  623. * Calculate the size of the return buffer.
  624. * The base size is the number of elements * the sizes of the
  625. * structures. Additional space for the strings is added below.
  626. * The minus one is to subtract the size of the u8 Source[1]
  627. * member because it is added below.
  628. *
  629. * But each PRT_ENTRY structure has a pointer to a string and
  630. * the size of that string must be found.
  631. */
  632. top_object_list = package_object->package.elements;
  633. for (index = 0; index < number_of_elements; index++) {
  634. /*
  635. * Dereference the sub-package
  636. */
  637. package_element = *top_object_list;
  638. /*
  639. * The sub_object_list will now point to an array of the
  640. * four IRQ elements: Address, Pin, Source and source_index
  641. */
  642. sub_object_list = package_element->package.elements;
  643. /*
  644. * Scan the irq_table_elements for the Source Name String
  645. */
  646. name_found = FALSE;
  647. for (table_index = 0; table_index < 4 && !name_found; table_index++) {
  648. if ((ACPI_TYPE_STRING == ACPI_GET_OBJECT_TYPE (*sub_object_list)) ||
  649. ((ACPI_TYPE_LOCAL_REFERENCE == ACPI_GET_OBJECT_TYPE (*sub_object_list)) &&
  650. ((*sub_object_list)->reference.opcode == AML_INT_NAMEPATH_OP))) {
  651. name_found = TRUE;
  652. }
  653. else {
  654. /*
  655. * Look at the next element
  656. */
  657. sub_object_list++;
  658. }
  659. }
  660. temp_size_needed += (sizeof (struct acpi_pci_routing_table) - 4);
  661. /*
  662. * Was a String type found?
  663. */
  664. if (name_found) {
  665. if (ACPI_GET_OBJECT_TYPE (*sub_object_list) == ACPI_TYPE_STRING) {
  666. /*
  667. * The length String.Length field does not include the
  668. * terminating NULL, add 1
  669. */
  670. temp_size_needed += ((acpi_size) (*sub_object_list)->string.length + 1);
  671. }
  672. else {
  673. temp_size_needed += acpi_ns_get_pathname_length (
  674. (*sub_object_list)->reference.node);
  675. }
  676. }
  677. else {
  678. /*
  679. * If no name was found, then this is a NULL, which is
  680. * translated as a u32 zero.
  681. */
  682. temp_size_needed += sizeof (u32);
  683. }
  684. /* Round up the size since each element must be aligned */
  685. temp_size_needed = ACPI_ROUND_UP_to_64_bITS (temp_size_needed);
  686. /*
  687. * Point to the next union acpi_operand_object
  688. */
  689. top_object_list++;
  690. }
  691. /*
  692. * Adding an extra element to the end of the list, essentially a NULL terminator
  693. */
  694. *buffer_size_needed = temp_size_needed + sizeof (struct acpi_pci_routing_table);
  695. return_ACPI_STATUS (AE_OK);
  696. }