Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 8th, 2012  |  syntax: None  |  size: 25.52 KB  |  hits: 17  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2.  * Copyright (c) 2008 Open Kernel Labs, Inc. (Copyright Holder).
  3.  * All rights reserved.
  4.  *
  5.  * 1. Redistribution and use of OKL4 (Software) in source and binary
  6.  * forms, with or without modification, are permitted provided that the
  7.  * following conditions are met:
  8.  *
  9.  *     (a) Redistributions of source code must retain this clause 1
  10.  *         (including paragraphs (a), (b) and (c)), clause 2 and clause 3
  11.  *         (Licence Terms) and the above copyright notice.
  12.  *
  13.  *     (b) Redistributions in binary form must reproduce the above
  14.  *         copyright notice and the Licence Terms in the documentation and/or
  15.  *         other materials provided with the distribution.
  16.  *
  17.  *     (c) Redistributions in any form must be accompanied by information on
  18.  *         how to obtain complete source code for:
  19.  *        (i) the Software; and
  20.  *        (ii) all accompanying software that uses (or is intended to
  21.  *        use) the Software whether directly or indirectly.  Such source
  22.  *        code must:
  23.  *        (iii) either be included in the distribution or be available
  24.  *        for no more than the cost of distribution plus a nominal fee;
  25.  *        and
  26.  *        (iv) be licensed by each relevant holder of copyright under
  27.  *        either the Licence Terms (with an appropriate copyright notice)
  28.  *        or the terms of a licence which is approved by the Open Source
  29.  *        Initative.  For an executable file, "complete source code"
  30.  *        means the source code for all modules it contains and includes
  31.  *        associated build and other files reasonably required to produce
  32.  *        the executable.
  33.  *
  34.  * 2. THIS SOFTWARE IS PROVIDED ``AS IS'' AND, TO THE EXTENT PERMITTED BY
  35.  * LAW, ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  36.  * THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  37.  * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED.  WHERE ANY WARRANTY IS
  38.  * IMPLIED AND IS PREVENTED BY LAW FROM BEING DISCLAIMED THEN TO THE
  39.  * EXTENT PERMISSIBLE BY LAW: (A) THE WARRANTY IS READ DOWN IN FAVOUR OF
  40.  * THE COPYRIGHT HOLDER (AND, IN THE CASE OF A PARTICIPANT, THAT
  41.  * PARTICIPANT) AND (B) ANY LIMITATIONS PERMITTED BY LAW (INCLUDING AS TO
  42.  * THE EXTENT OF THE WARRANTY AND THE REMEDIES AVAILABLE IN THE EVENT OF
  43.  * BREACH) ARE DEEMED PART OF THIS LICENCE IN A FORM MOST FAVOURABLE TO
  44.  * THE COPYRIGHT HOLDER (AND, IN THE CASE OF A PARTICIPANT, THAT
  45.  * PARTICIPANT). IN THE LICENCE TERMS, "PARTICIPANT" INCLUDES EVERY
  46.  * PERSON WHO HAS CONTRIBUTED TO THE SOFTWARE OR WHO HAS BEEN INVOLVED IN
  47.  * THE DISTRIBUTION OR DISSEMINATION OF THE SOFTWARE.
  48.  *
  49.  * 3. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY OTHER PARTICIPANT BE
  50.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  51.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  52.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  53.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  54.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  55.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  56.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  57.  */
  58.  
  59. #include <bootinfo/bootinfo.h>
  60. #include "bootinfo_priv.h"
  61.  
  62. /** @todo FIXME: doxygen headers, split prototypes out - awiggins. */
  63.  
  64. static inline int
  65. name_is_valid(bi_name_t name)
  66. {
  67.     return name != BI_NAME_INVALID;
  68. }
  69.  
  70. static size_t
  71. true_str_size(char * s, size_t n)
  72. {
  73.     char * end = s + n - 1;
  74.  
  75.     while (end >= s && *end == '\0') {
  76.         end--;
  77.     }
  78.  
  79.     return end < s ? 0 : end - s + 1;
  80. }
  81.  
  82. /** @todo FIXME: Break this function down into smaller functions - awiggins. */
  83. int
  84. bootinfo_parse(void * buffer, const bi_callbacks_t * callbacks,
  85.         void * user_data)
  86. {
  87.     char * this_rec = (char *)buffer;
  88.     bi_user_data_t data;
  89.     int ret = 1; /* Assume that we'll return an error. */
  90.  
  91.     data.total_pools   = 3;
  92.     data.total_pds     = 0;
  93.     data.total_mss     = 0;
  94.     data.total_threads = 0;
  95.     data.total_caps    = 0;
  96.     data.total_zones   = 0;
  97.     data.rec_num       = 0;
  98.     data.user_data     = user_data;
  99.  
  100.     /* 1) Check for the header record. */
  101.     if (((bi_hdr_t *)this_rec)->op != BI_OP_HEADER) {
  102.         ERROR_PRINT("Boot Info header not found (found 0x%lx @ %p)\n",
  103.                     (long) ((bi_hdr_t *)this_rec)->op, this_rec);
  104.         return 1;
  105.     }
  106.     /*------------------------------------------------------------------------*/
  107.     /*
  108.      * First Pass: Run through the operations and calculate the
  109.      * total number of objects that will be created.  This
  110.      * information will be used to determine the size of the
  111.      * object buffers.
  112.      */
  113.  
  114.     BOOTINFO_PRINT("First pass: Calculating sizes and initialising memory.\n");
  115.  
  116.     while (1) {
  117.         bi_hdr_t * current = (bi_hdr_t *)this_rec;
  118.  
  119.         switch (current->op) {
  120.         case BI_OP_HEADER: {
  121.             bi_header_t * rec = (bi_header_t *)current;
  122.  
  123.             BOOTINFO_PRINT("HEADER: stack_base: 0x%lx stack_end: 0x%lx, heap_base: 0x%lx, heap_end: 0x%lx\n",
  124.                     (long)rec->stack_base, (long)rec->stack_end,
  125.                     (long)rec->heap_base, (long)rec->heap_end);
  126.  
  127.             if (rec->magic != BI_MAGIC || rec->version != BI_VERSION) {
  128.                 ERROR_PRINT("Record %d: Bad bootinfo header found.\n",
  129.                             data.rec_num);
  130.                 return 1;
  131.             }
  132.             break;
  133.         }
  134.         case BI_OP_END:
  135.             goto end_first_pass;
  136.  
  137.         case BI_OP_INIT_MEM: {
  138.             bi_init_mem_t * rec = (bi_init_mem_t *)current;
  139.  
  140.             BOOTINFO_PRINT("MEM_INIT (virt_base: 0x%lx, virt_end: 0x%lx, phys_base: 0x%lx, phys_end: 0x%lx)\n",
  141.                            (long)rec->virt_base, (long)rec->virt_end,
  142.                            (long)rec->phys_base, (long)rec->phys_end);
  143.                
  144.             if (rec->virt_base >= rec->virt_end ||
  145.                     rec->phys_base >= rec->phys_end) {
  146.                 ERROR_PRINT("Record %d: Invalid address ranges: virt_base: 0x%lx, virt_end: 0x%lx, phys_base: 0x%lx, phys_end: 0x%lx\n",
  147.                             data.rec_num, (long)rec->virt_base,
  148.                             (long)rec->virt_end, (long)rec->phys_base,
  149.                             (long)rec->phys_end);
  150.                
  151.                 return 1;
  152.             }
  153.            
  154.             /*
  155.              * Initialise the memory subsystem.
  156.              *
  157.              * This is done in the first pass because the amount of
  158.              * memory in the heap at startup is limited and there may
  159.              * not be enough for all of the arrays we need to
  160.              * malloc().  Initialising here will give more_core() the
  161.              * ability to expand into new memsections.
  162.              */
  163.             if (callbacks->init_mem != NULL) {
  164.                 callbacks->init_mem((uintptr_t)rec->virt_base,
  165.                         (uintptr_t)rec->virt_end, (uintptr_t)rec->phys_base,
  166.                         (uintptr_t)rec->phys_end, &data);
  167.             }
  168.  
  169.             break;
  170.         }
  171.         case BI_OP_NEW_PD:
  172.             data.total_pds++;
  173.             break;
  174.  
  175.         case BI_OP_NEW_MS:
  176.             data.total_mss++;
  177.             break;
  178.  
  179.         case BI_OP_NEW_THREAD:
  180.             data.total_threads++;
  181.             break;
  182.  
  183.         case BI_OP_NEW_CAP:
  184.             data.total_caps++;
  185.             break;
  186.  
  187.         case BI_OP_NEW_POOL:
  188.             data.total_pools++;
  189.             break;
  190.  
  191.         case BI_OP_NEW_ZONE:
  192.             data.total_zones++;
  193.             break;
  194.  
  195.             /* These ops don't allocate any bootinfo objects. */
  196.         case BI_OP_ADD_VIRT_MEM:
  197.         case BI_OP_ADD_PHYS_MEM:
  198.         case BI_OP_REGISTER_STACK:
  199.         case BI_OP_RUN_THREAD:
  200.         case BI_OP_MAP:
  201.         case BI_OP_ATTACH:
  202.         case BI_OP_GRANT:
  203.         case BI_OP_GRANT_CAP:
  204.         case BI_OP_OBJECT_EXPORT:
  205.         case BI_OP_STRUCT_EXPORT:
  206.         case BI_OP_ARGV:
  207.         case BI_OP_REGISTER_SERVER:
  208.         case BI_OP_REGISTER_CALLBACK:
  209.         case BI_OP_REGISTER_ENV:
  210.         case BI_OP_GRANT_INTERRUPT:
  211.         case BI_OP_SECURITY_CONTROL:
  212.         case BI_OP_ADD_ZONE_WINDOW:
  213.         case BI_OP_KERNEL_INFO:
  214.             break;
  215.  
  216.         default:
  217.             ERROR_PRINT("Record %d: Unknown opcode %ld\n",
  218.                         data.rec_num, (long)current->op);
  219.             return 1;
  220.         }
  221.  
  222.         this_rec += current->size;
  223.         data.rec_num++;
  224.     }
  225.  
  226. end_first_pass:
  227.  
  228.     if (callbacks->init != NULL) {
  229.         callbacks->init(&data);
  230.     }
  231.    
  232.     BOOTINFO_PRINT("Second pass: Processing operation.\n");
  233.  
  234.     this_rec = (char *)buffer;
  235.     data.rec_num = 0;
  236.  
  237.     while (1) {
  238.         bi_hdr_t * current = (bi_hdr_t *)this_rec;
  239.  
  240.         BOOTINFO_PRINT("current is: %p\n", this_rec);
  241.  
  242.         switch (current->op) {
  243.         case BI_OP_HEADER:
  244.             break;
  245.  
  246.         case BI_OP_END:
  247.             BOOTINFO_PRINT("END\n");
  248.             goto success;
  249.  
  250.         case BI_OP_NEW_PD: {
  251.             bi_new_pd_t * rec = (bi_new_pd_t *)current;
  252.  
  253.             BOOTINFO_PRINT("NEW PD (owner: %ld)\n", rec->owner);
  254.  
  255.             if (callbacks->new_pd != NULL) {
  256.                 bi_name_t name = callbacks->new_pd((bi_name_t)rec->owner,
  257.                         &data);
  258.  
  259.                 if (name_is_valid(name)) {
  260.                     BOOTINFO_PRINT("<--- Created PD %d \n", name);
  261.                 }
  262.                 else {
  263.                     goto quit;
  264.                 }
  265.             }
  266.            
  267.             break;
  268.         }
  269.         case BI_OP_NEW_MS: {
  270.             bi_new_ms_t * rec = (bi_new_ms_t *)current;
  271.  
  272.             BOOTINFO_PRINT
  273.                 ("NEW MS (owner: %ld, base: 0x%lx, size: 0x%lx, flags 0x%lx, attr: 0x%lx, physpool: 0x%lx, virtpool: 0x%lx, zone: %ld)\n",
  274.                  (long)rec->owner, (long)rec->base, (long)rec->size,
  275.                  (long)rec->flags, (long)rec->attr, (long)rec->physpool,
  276.                  (long)rec->virtpool, (long)rec->zone);
  277.  
  278.             if (callbacks->new_ms != NULL) {
  279.                 bi_name_t name = callbacks->new_ms((bi_name_t)rec->owner,
  280.                         (uintptr_t)rec->base, (uintptr_t)rec->size,
  281.                         (uintptr_t)rec->flags, (uintptr_t)rec->attr,
  282.                         (bi_name_t)rec->physpool, (bi_name_t)rec->virtpool,
  283.                         (bi_name_t)rec->zone, &data);
  284.  
  285.                 if (name_is_valid(name)) {
  286.                     BOOTINFO_PRINT("<--- Created MS %d \n", name);
  287.                 }
  288.                 else {
  289.                     goto quit;
  290.                 }
  291.             }
  292.  
  293.             break;
  294.         }
  295.         case BI_OP_ADD_VIRT_MEM: {
  296.             bi_add_virt_mem_t * rec = (bi_add_virt_mem_t *)current;
  297.  
  298.             BOOTINFO_PRINT("ADD VIRT MEM (pool: 0x%lx, base: 0x%lx, end: 0x%lx)\n",
  299.                            (long)rec->pool, (long)rec->base, (long)rec->end);
  300.  
  301.             if (callbacks->add_virt_mem != NULL) {
  302.                 if (callbacks->add_virt_mem((bi_name_t)rec->pool,
  303.                         (uintptr_t)rec->base, (uintptr_t)rec->end,
  304.                         &data) != 0) {
  305.                     goto quit;
  306.                 }
  307.             }
  308.  
  309.             break;
  310.         }
  311.         case BI_OP_ADD_PHYS_MEM: {
  312.             bi_add_phys_mem_t * rec = (bi_add_phys_mem_t *)current;
  313.  
  314.             BOOTINFO_PRINT("ADD PHYS MEM (pool: 0x%lx, base: 0x%lx, end: 0x%lx)\n",
  315.                            (long)rec->pool, (long)rec->base, (long)rec->end);
  316.  
  317.             if (callbacks->add_phys_mem != NULL) {
  318.                 if (callbacks->add_phys_mem((bi_name_t)rec->pool,
  319.                                             (uintptr_t)rec->base,
  320.                                             (uintptr_t)rec->end,
  321.                                             &data) != 0) {
  322.                     goto quit;
  323.                 }
  324.             }
  325.  
  326.             break;
  327.         }
  328.         case BI_OP_NEW_THREAD: {
  329.             bi_new_thread_t * rec = (bi_new_thread_t *)current;
  330.             size_t str_len = true_str_size((char *)rec->name,
  331.                                            current->size - offsetof(bi_new_thread_t, name));
  332.  
  333.             BOOTINFO_PRINT("NEW THREAD (pd: %d, ip: 0x%lx, user_main: 0x%lx, pri: %d, name: \"%.*s\")\n",
  334.                            (int)rec->owner, (long)rec->ip,
  335.                            (long)rec->user_main, (int)rec->priority,
  336.                            str_len, (char *) rec->name);
  337.  
  338.             if (callbacks->new_thread != NULL) {
  339.                 bi_name_t name =
  340.                     callbacks->new_thread((bi_name_t)rec->owner,
  341.                                           (uintptr_t)rec->ip,
  342.                                           (uintptr_t)rec->user_main,
  343.                                           (int)rec->priority,
  344.                                           (char *)rec->name, str_len,
  345.                                           &data);
  346.  
  347.                 if (name_is_valid(name)) {
  348.                     BOOTINFO_PRINT("<--- Created Thread %d\n", name);
  349.                 }
  350.                 else {
  351.                     goto quit;
  352.                 }
  353.             }
  354.  
  355.             break;
  356.         }
  357.         case BI_OP_RUN_THREAD: {
  358.             bi_run_thread_t * rec = (bi_run_thread_t *)current;
  359.  
  360.             BOOTINFO_PRINT("RUN THREAD (thread: %d)\n", (int)rec->name);
  361.  
  362.             if (callbacks->run_thread != NULL) {
  363.                 if (callbacks->run_thread((bi_name_t)rec->name,
  364.                                           &data) != 0) {
  365.                     goto quit;
  366.                 }
  367.             }
  368.  
  369.             break;
  370.         }
  371.         case BI_OP_MAP: {
  372.             bi_map_t * rec = (bi_map_t *)current;
  373.  
  374.             BOOTINFO_PRINT("MAP (vaddr: 0x%lx, size %d, paddr: 0x%lx, scrub: %d, mode : 0x%lx)\n",
  375.                            rec->vaddr, (int)rec->size, rec->paddr,
  376.                            (int)rec->scrub, rec->mode);
  377.  
  378.             if (callbacks->map != NULL) {
  379.                 if (callbacks->map((uintptr_t)rec->vaddr, (uintptr_t)rec->size,
  380.                         (uintptr_t)rec->paddr, (int)rec->scrub,
  381.                         (unsigned)rec->mode, &data) != 0) {
  382.                     goto quit;
  383.                 }
  384.             }
  385.  
  386.             break;
  387.         }
  388.         case BI_OP_ATTACH: {
  389.             bi_attach_t * rec = (bi_attach_t *)current;
  390.  
  391.             BOOTINFO_PRINT("ATTACH (pd: %d, ms: %d, rights: 0x%x)\n",
  392.                            (int)rec->pd, (int)rec->ms, (int)rec->rights);
  393.  
  394.             if (callbacks->attach != NULL) {
  395.                 if (callbacks->attach((bi_name_t)rec->pd, (bi_name_t)rec->ms,
  396.                         (int)rec->rights, &data) != 0) {
  397.                     goto quit;
  398.                 }
  399.             }
  400.  
  401.             break;
  402.         }
  403.         case BI_OP_GRANT: {
  404.             bi_grant_t * rec = (bi_grant_t *)current;
  405.  
  406.             BOOTINFO_PRINT("GRANT (pd: %d, obj: %d, rights: 0x%x)\n",
  407.                            (int)rec->pd, (int)rec->obj, (int)rec->rights);
  408.  
  409.             if (callbacks->grant != NULL) {
  410.                 if (callbacks->grant((bi_name_t)rec->pd, (bi_name_t)rec->obj,
  411.                         (int)rec->rights, &data) != 0) {
  412.                     goto quit;
  413.                 }
  414.             }
  415.  
  416.             break;
  417.         }
  418.         case BI_OP_ARGV: {
  419.             bi_argv_t * rec = (bi_argv_t *)current;
  420.             size_t str_len = true_str_size((char *)rec->arg,
  421.                                            current->size - offsetof(bi_argv_t, arg));
  422.  
  423.             BOOTINFO_PRINT("ARGV (thread: %d, arg: \"%.*s\"\n",
  424.                            (int)rec->thread, str_len, (char *)rec->arg);
  425.  
  426.             if (callbacks->argv != NULL) {
  427.                 if (callbacks->argv((bi_name_t)rec->thread, (char *)rec->arg,
  428.                         str_len, &data) != 0) {
  429.                     goto quit;
  430.                 }
  431.             }
  432.  
  433.             break;
  434.         }
  435.         case BI_OP_REGISTER_SERVER: {
  436.             bi_register_server_t * rec = (bi_register_server_t *)current;
  437.  
  438.             BOOTINFO_PRINT("REGISTER SERVER (thread: %d, ms: %d)\n",
  439.                            (int)rec->thread, (int)rec->ms);
  440.  
  441.             if (callbacks->register_server != NULL) {
  442.                 if (callbacks->register_server((bi_name_t)rec->thread,
  443.                         (bi_name_t)rec->ms, &data) != 0) {
  444.                     goto quit;
  445.                 }
  446.             }
  447.  
  448.             break;
  449.         }
  450.         case BI_OP_REGISTER_CALLBACK: {
  451.             bi_register_callback_t * rec = (bi_register_callback_t *)current;
  452.  
  453.             BOOTINFO_PRINT("REGISTER CALLBACK (pd: %d, ms: %d)\n",
  454.                            (int)rec->pd, (int)rec->ms);
  455.  
  456.             if (callbacks->register_callback != NULL) {
  457.                 if (callbacks->register_callback((bi_name_t)rec->pd,
  458.                         (bi_name_t)rec->ms, &data) != 0) {
  459.                     goto quit;
  460.                 }
  461.             }
  462.  
  463.             break;
  464.         }
  465.         case BI_OP_REGISTER_STACK: {
  466.             bi_register_stack_t * rec = (bi_register_stack_t *)current;
  467.  
  468.             BOOTINFO_PRINT("REGISTER STACK (thead: %d, ms: %d)\n",
  469.                            (int)rec->thread, (int)rec->ms);
  470.  
  471.             if (callbacks->register_stack != NULL) {
  472.                 if (callbacks->register_stack((bi_name_t)rec->thread,
  473.                         (bi_name_t)rec->ms, &data) != 0) {
  474.                     goto quit;
  475.                 }
  476.             }
  477.  
  478.             break;
  479.         }
  480.         case BI_OP_INIT_MEM: {
  481.             bi_init_mem_t * rec = (bi_init_mem_t *)current;
  482.  
  483.             if (callbacks->init_mem2 != NULL) {
  484.                 if (callbacks->init_mem2((uintptr_t)rec->virt_base,
  485.                         (uintptr_t)rec->virt_end, (uintptr_t)rec->phys_base,
  486.                         (uintptr_t)rec->phys_end, &data) != 0) {
  487.                     goto quit;
  488.                 }
  489.             }
  490.  
  491.             break;
  492.         }
  493.         case BI_OP_NEW_CAP: {
  494.             bi_new_cap_t * rec = (bi_new_cap_t *)current;
  495.  
  496.             BOOTINFO_PRINT("NEW_CAP (obj: %d, rights: 0x%lx)\n",
  497.                            (int)rec->obj, (long)rec->rights);
  498.  
  499.             if (callbacks->new_cap != NULL) {
  500.                 bi_name_t name = callbacks->new_cap((bi_name_t)rec->obj,
  501.                         (bi_cap_rights_t)rec->rights, &data);
  502.  
  503.                 if (name_is_valid(name)) {
  504.                     BOOTINFO_PRINT("<--- Created CAP %d\n", name);
  505.                 }
  506.                 else {
  507.                     goto quit;
  508.                 }
  509.             }
  510.  
  511.             break;
  512.         }
  513.         case BI_OP_GRANT_CAP: {
  514.             bi_grant_cap_t * rec = (bi_grant_cap_t *)current;
  515.  
  516.             BOOTINFO_PRINT("GRANT_CAP (pd: %d, cap: %d)\n",
  517.                            (int)rec->pd, (int)rec->cap);
  518.  
  519.             if (callbacks->grant_cap != NULL) {
  520.                 if (callbacks->grant_cap((bi_name_t)rec->pd,
  521.                         (bi_name_t)rec->cap, &data) != 0) {
  522.                     goto quit;
  523.                 }
  524.             }
  525.  
  526.             break;
  527.         }
  528.         case BI_OP_OBJECT_EXPORT: {
  529.             bi_object_export_t * rec = (bi_object_export_t *)current;
  530.             size_t str_len = true_str_size((char*)rec->key,
  531.                                            current->size - offsetof(bi_object_export_t, key));
  532.  
  533.             BOOTINFO_PRINT
  534.                 ("OBJECT_EXPORT (pd: %d, key: \"%.*s\", obj: %d, type: %d)\n",
  535.                  (int)rec->pd, (int) str_len, (char*) rec->key, (int)rec->obj,
  536.                  (int)rec->type);
  537.  
  538.             if (callbacks->export_object != NULL) {
  539.                 if (callbacks->export_object((bi_name_t)rec->pd,
  540.                         (bi_name_t)rec->obj, (bi_export_type_t)rec->type,
  541.                         (char *)rec->key, str_len, &data) != 0) {
  542.                     goto quit;
  543.                 }
  544.             }
  545.  
  546.             break;
  547.         }
  548.         case BI_OP_STRUCT_EXPORT: {
  549.             bi_struct_export_t * rec = (bi_struct_export_t *)current;
  550.             size_t str_len = true_str_size((char *)rec->key,
  551.                                            current->size - offsetof(bi_struct_export_t, key));
  552.  
  553.             BOOTINFO_PRINT
  554.                 ("STRUCT_EXPORT (pd: %d, key: \"%.*s\", first: 0x%lx, second: 0x%lx, third: 0x%lx, fourth: 0x%lx, fifth: 0x%lx, sixth: 0x%lx, type: %d)\n",
  555.                  (int)rec->pd, (int) str_len, (char*)rec->key,
  556.                  (long)rec->first, (long)rec->second, (long)rec->third,
  557.                  (long)rec->fourth, (long)rec->fifth, (long)rec->sixth,
  558.                  (int)rec->type);
  559.  
  560.             if (callbacks->export_struct != NULL) {
  561.                 if (callbacks->export_struct((bi_name_t)rec->pd,
  562.                         (bi_export_type_t)rec->type, (char *)rec->key,
  563.                         str_len, (uintptr_t)rec->first, (uintptr_t)rec->second,
  564.                         (uintptr_t)rec->third, (uintptr_t)rec->fourth,
  565.                         (uintptr_t)rec->fifth, (uintptr_t)rec->sixth,
  566.                         &data) != 0) {
  567.                     goto quit;
  568.                 }
  569.             }
  570.  
  571.             break;
  572.         }
  573.         case BI_OP_REGISTER_ENV: {
  574.             bi_register_env_t * rec = (bi_register_env_t *)current;
  575.  
  576.             BOOTINFO_PRINT("REGISTER ENVIRONMENT (pd: %d, ms: %d)\n",
  577.                            (int)rec->pd, (int)rec->ms);
  578.  
  579.             if (callbacks->register_env != NULL) {
  580.                 if (callbacks->register_env((bi_name_t)rec->pd,
  581.                         (bi_name_t)rec->ms, &data) != 0) {
  582.                     goto quit;
  583.                 }
  584.             }
  585.  
  586.             break;
  587.         }
  588.         case BI_OP_NEW_POOL: {
  589.             bi_new_pool_t * rec = (bi_new_pool_t *)current;
  590.  
  591.             BOOTINFO_PRINT("NEW POOL (is_virtual: %d)\n", (int)rec->is_virtual);
  592.  
  593.             if (callbacks->new_pool != NULL) {
  594.                 bi_name_t name = callbacks->new_pool((int) rec->is_virtual,
  595.                         &data);
  596.  
  597.                 if (name_is_valid(name)) {
  598.                     BOOTINFO_PRINT("<--- Created %s Pool %d\n",
  599.                                    rec->is_virtual ? "Virtual" : "Physical",
  600.                                    name);
  601.                 }
  602.                 else {
  603.                     goto quit;
  604.                 }
  605.             }
  606.  
  607.             break;
  608.         }
  609.         case BI_OP_GRANT_INTERRUPT: {
  610.             bi_grant_interrupt_t * rec = (bi_grant_interrupt_t *)current;
  611.  
  612.             BOOTINFO_PRINT("GRANT INTERRUPT (tid: %d, irq: %d)\n",
  613.                            (int)rec->thread, (int)rec->irq);
  614.  
  615.             if (callbacks->grant_interrupt != NULL) {
  616.                 if (callbacks->grant_interrupt((bi_name_t)rec->thread,
  617.                         (int)rec->irq, &data) != 0) {
  618.                     goto quit;
  619.                 }
  620.             }
  621.  
  622.             break;
  623.         }
  624.         case BI_OP_SECURITY_CONTROL: {
  625.             bi_security_control_t * rec = (bi_security_control_t *)current;
  626.  
  627.             BOOTINFO_PRINT("SECURITY CONTROL (pd: %d, obj: %d, type: %d)\n",
  628.                            (int)rec->pd, (int)rec->obj, (int)rec->type);
  629.  
  630.             if (callbacks->security_control != NULL) {
  631.                 if (callbacks->security_control((bi_name_t)rec->pd,
  632.                         (bi_name_t)rec->obj,
  633.                         (bi_security_control_type_t)rec->type, &data) != 0) {
  634.                     goto quit;
  635.                 }
  636.             }
  637.  
  638.             break;
  639.         }
  640.         case BI_OP_NEW_ZONE: {
  641.             bi_new_zone_t * rec = (bi_new_zone_t *)current;
  642.  
  643.             BOOTINFO_PRINT("NEW ZONE (pool: %d)\n", (int)rec->pool);
  644.  
  645.             if (callbacks->new_zone != NULL) {
  646.                 bi_name_t name = callbacks->new_zone((bi_name_t)rec->pool,
  647.                         &data);
  648.  
  649.                 if (name_is_valid(name)) {
  650.                     BOOTINFO_PRINT("<--- Created Zone %d\n", name);
  651.                 }
  652.                 else {
  653.                     goto quit;
  654.                 }
  655.             }
  656.  
  657.             break;
  658.         }
  659.         case BI_OP_ADD_ZONE_WINDOW: {
  660.             bi_add_zone_window_t * rec = (bi_add_zone_window_t *)current;
  661.  
  662.             BOOTINFO_PRINT("ADD ZONE WINDOW (zone: %d base: 0x%lx)\n",
  663.                            (int) rec->zone, (long)rec->base);
  664.  
  665.             if (callbacks->add_zone_window != NULL) {
  666.                 if (callbacks->add_zone_window((bi_name_t) rec->zone,
  667.                         (size_t)rec->base, &data) != 0) {
  668.                     goto quit;
  669.                 }
  670.             }
  671.             break;
  672.         }
  673.         case BI_OP_KERNEL_INFO: {
  674.             bi_kernel_info_t * rec = (bi_kernel_info_t *)current;
  675.            
  676.             BOOTINFO_PRINT("KERNEL INFO (spaces: %d, mutexes: %d, caps: %d)\n",
  677.                            (int)rec->max_spaces, (int)rec->max_mutexes,
  678.                            (int)rec->max_root_caps);
  679.  
  680.             if (callbacks->kernel_info != NULL) {
  681.                 if (callbacks->kernel_info((int)rec->max_spaces,
  682.                         (int)rec->max_mutexes, (int)rec->max_root_caps,
  683.                         &data) != 0) {
  684.                     goto quit;
  685.                 }
  686.             }
  687.  
  688.             break;
  689.         }
  690.         default:
  691.             ERROR_PRINT("Record %d: Unknown opcode %ld\n",
  692.                         data.rec_num, (long)current->op);
  693.  
  694.             goto quit;
  695.         }
  696.        
  697.         this_rec += current->size;
  698.         data.rec_num++;
  699.     }
  700.  
  701. success:
  702.     /* Success is at hand! */
  703.     ret = 0;
  704.  
  705. quit:
  706.     if (callbacks->cleanup != NULL) {
  707.         if (callbacks->cleanup(&data) != 0) {
  708.             ret = 1;
  709.         }
  710.     }
  711.  
  712.     return ret;
  713. }