]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/acpi.cc
update
[l4.git] / l4 / pkg / io / server / src / acpi.cc
1 /*
2  * (c) 2011 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *          Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10
11 #include <cstdio>
12 #include <cstdlib>
13
14 #include "debug.h"
15 #include "pci.h"
16 #include "acpi_l4.h"
17 #include "__acpi.h"
18 #include "cfg.h"
19 #include "main.h"
20 #include "phys_space.h"
21
22 extern "C" {
23 #include "acpi.h"
24 #include "accommon.h"
25 #include "acresrc.h"
26 #include "acnamesp.h"
27 }
28
29 #include <errno.h>
30 #include <l4/cxx/list>
31
32 #define _COMPONENT              ACPI_BUS_COMPONENT
33 ACPI_MODULE_NAME("l4main");
34
35 namespace {
36
37 struct Prt_entry : public cxx::List_item
38 {
39   unsigned slot;
40   unsigned char pin;
41   acpica_pci_irq irq;
42 };
43
44 class Acpi_pci_irq_router_rs : public Resource_space
45 {
46 public:
47   Prt_entry *_prt;
48
49 public:
50   Acpi_pci_irq_router_rs() : _prt(0) {}
51
52   int add_prt_entry(ACPI_HANDLE obj, ACPI_PCI_ROUTING_TABLE *e);
53   int find(int device, int pin, struct acpica_pci_irq **irq);
54   bool request(Resource *parent, Device *, Resource *child, Device *cdev);
55   bool alloc(Resource *, Device *, Resource *, Device *, bool)
56   { return false; }
57 };
58
59
60 bool
61 Acpi_pci_irq_router_rs::request(Resource *parent, Device *,
62                                 Resource *child, Device *cdev)
63 {
64   if (dlevel(DBG_ALL))
65     {
66       printf("requesting IRQ resource: ");
67       cdev->dump(2);
68       child->dump(2);
69       printf(" at ACPI IRQ routing resource\n");
70     }
71
72   Adr_resource *cr = dynamic_cast<Adr_resource*>(child);
73
74   if (!cr)
75     {
76       child->parent(parent);
77       return true;
78     }
79
80   Hw::Device *cd = dynamic_cast<Hw::Device*>(cdev);
81
82   if (!cd)
83     return false;
84
85   struct acpica_pci_irq *irq = 0;
86
87   if (find(cd->adr() >> 16, cr->start(), &irq) < 0)
88     return false;
89
90   if (!irq)
91     return false;
92
93   cr->del_flags(Resource::F_relative);
94   cr->start(irq->irq);
95   cr->del_flags(Resource::Irq_info_base * 3);
96   unsigned flags = 0;
97   flags |= (!irq->trigger) * Resource::Irq_info_base;
98   flags |= (!!irq->polarity) * Resource::Irq_info_base * 2;
99   cr->add_flags(flags);
100
101   cr->parent(parent);
102
103   return true;
104 }
105
106 enum Acpi_irq_model_id {
107         ACPI_IRQ_MODEL_PIC = 0,
108         ACPI_IRQ_MODEL_IOAPIC,
109         ACPI_IRQ_MODEL_IOSAPIC,
110         ACPI_IRQ_MODEL_PLATFORM,
111         ACPI_IRQ_MODEL_COUNT
112 };
113
114 static ACPI_STATUS
115 get_irq_cb(ACPI_RESOURCE *res, void *ctxt)
116 {
117   acpica_pci_irq *irq = (acpica_pci_irq*)ctxt;
118   if (!res)
119     return AE_OK;
120
121   switch (res->Type)
122     {
123     case ACPI_RESOURCE_TYPE_IRQ:
124       irq->irq = res->Data.Irq.Interrupts[0];
125       irq->polarity = res->Data.Irq.Polarity;
126       irq->trigger  = res->Data.Irq.Triggering;
127       return AE_OK;
128
129     case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
130       irq->irq = res->Data.ExtendedIrq.Interrupts[0];
131       irq->polarity = res->Data.ExtendedIrq.Polarity;
132       irq->trigger  = res->Data.ExtendedIrq.Triggering;
133       return AE_OK;
134
135     default:
136       return AE_OK;
137     }
138 }
139
140 int
141 Acpi_pci_irq_router_rs::add_prt_entry(ACPI_HANDLE obj,
142                                       ACPI_PCI_ROUTING_TABLE *e)
143 {
144   if (!e)
145     return -EINVAL;
146
147   Prt_entry *ne = new Prt_entry();
148   if (!ne)
149     return -ENOMEM;
150
151   ne->slot = (e->Address >> 16) & 0xffff;
152   ne->pin = e->Pin;
153
154   ne->irq.irq = e->SourceIndex;
155   ne->irq.polarity = ACPI_ACTIVE_LOW;
156   ne->irq.trigger = ACPI_LEVEL_SENSITIVE;
157   if (e->Source[0])
158     {
159       ACPI_HANDLE link;
160       d_printf(DBG_DEBUG, " (dev[%s][%d]) ", e->Source, e->SourceIndex);
161       ACPI_STATUS status;
162       status = AcpiGetHandle(obj, e->Source, &link);
163       if (ACPI_FAILURE(status))
164         {
165           d_printf(DBG_WARN, "\nWARNING: Could not find PCI IRQ Link Device...\n");
166           return -ENODEV;
167         }
168
169       status = AcpiWalkResources(link, (char*)"_CRS", get_irq_cb, &ne->irq);
170       if (ACPI_FAILURE(status))
171         {
172           d_printf(DBG_WARN, "\nWARNING: Could not evaluate _CRS of PCI IRQ Link Device\n");
173           return -ENODEV;
174         }
175     }
176
177   _prt = cxx::List_item::push_back(_prt, ne);
178   return 0;
179 }
180
181 int
182 Acpi_pci_irq_router_rs::find(int device, int pin, struct acpica_pci_irq **irq)
183 {
184   Prt_entry::T_iter<Prt_entry> c = _prt;
185   while (*c)
186     {
187       if (c->slot == (unsigned)device && c->pin == pin)
188         {
189           *irq = &c->irq;
190           return 0;
191         }
192
193       ++c;
194     }
195
196   return -ENODEV;
197 }
198
199
200 static int acpi_bus_init_irq(void)
201 {
202   ACPI_STATUS status = AE_OK;
203   ACPI_OBJECT arg = { ACPI_TYPE_INTEGER };
204   ACPI_OBJECT_LIST arg_list = { 1, &arg };
205   char const *message = NULL;
206
207
208   //int acpi_irq_model = ACPI_IRQ_MODEL_PIC;
209   int acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
210   /*
211    * Let the system know what interrupt model we are using by
212    * evaluating the \_PIC object, if exists.
213    */
214
215   switch (acpi_irq_model) {
216     case ACPI_IRQ_MODEL_PIC:
217       message = "PIC";
218       break;
219     case ACPI_IRQ_MODEL_IOAPIC:
220       message = "IOAPIC";
221       break;
222     case ACPI_IRQ_MODEL_IOSAPIC:
223       message = "IOSAPIC";
224       break;
225     case ACPI_IRQ_MODEL_PLATFORM:
226       message = "platform specific model";
227       break;
228     default:
229       d_printf(DBG_ERR, "ERROR: Unknown interrupt routing model\n");
230       return -1;
231   }
232
233   d_printf(DBG_INFO, "Using %s for interrupt routing\n", message);
234
235   arg.Integer.Value = acpi_irq_model;
236
237   status = AcpiEvaluateObject(NULL, (char*)"\\_PIC", &arg_list, NULL);
238   if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
239       ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC"));
240       return -1;
241   }
242
243   return 0;
244 }
245
246
247 struct Discover_ctxt
248 {
249   Hw::Device *last_device;
250   Hw::Device *current_bus;
251   unsigned level;
252 };
253
254 class Acpi_res_discover : public Hw::Discover_res_if
255 {
256 public:
257   Acpi_res_discover(ACPI_HANDLE obj) : obj(obj) {}
258
259   void discover_resources(Hw::Device *host);
260   void setup_resources(Hw::Device *) {}
261
262 private:
263   void discover_prt(Hw::Device *host);
264   void discover_crs(Hw::Device *host);
265
266   ACPI_HANDLE obj;
267 };
268
269 void
270 Acpi_res_discover::discover_prt(Hw::Device *host)
271 {
272   ACPI_BUFFER buf;
273   ACPI_STATUS status;
274   ACPI_HANDLE handle;
275
276   status = AcpiGetHandle(obj, (char*)"_PRT", &handle);
277
278   // no PRT!!
279   if (ACPI_FAILURE(status))
280     {
281       Resource *r = new Pci_irq_router_res<Pci_pci_bridge_irq_router_rs>();
282       host->add_resource(r);
283       return;
284     }
285
286 #if 0
287   ret_buf.Length = sizeof (buffer);
288   ret_buf.Pointer = buffer;
289
290   status = AcpiGetName (obj, ACPI_FULL_PATHNAME, &ret_buf);
291
292   if (ACPI_FAILURE (status))
293     AcpiOsPrintf ("Could not convert name to pathname\n");
294   else
295     AcpiOsPrintf ("ACPI: PCI IRQ routing [%s._PRT]\n", buffer);
296 #endif
297
298   buf.Length = ACPI_ALLOCATE_BUFFER;
299
300   status = AcpiGetIrqRoutingTable(obj, &buf);
301
302   if (ACPI_FAILURE(status))
303     {
304       d_printf(DBG_ERR, "ERROR: while getting PRT for [%s]\n", "buffer");
305       Resource *r = new Pci_irq_router_res<Pci_pci_bridge_irq_router_rs>();
306       host->add_resource(r);
307       return;
308     }
309
310   typedef Pci_irq_router_res<Acpi_pci_irq_router_rs> Irq_res;
311   Irq_res *r = new Irq_res();
312
313   char *p = (char*)buf.Pointer;
314   char *e = (char*)buf.Pointer + buf.Length;
315   while (1)
316     {
317       ACPI_PCI_ROUTING_TABLE *prt = (ACPI_PCI_ROUTING_TABLE *)p;
318       if (prt->Length == 0)
319         break;
320
321       if (p + prt->Length > e)
322         break;
323
324       int err = r->provided()->add_prt_entry(obj, prt);
325       if (err < 0)
326         return;
327
328       p += prt->Length;
329     }
330
331   host->add_resource(r);
332 }
333
334 static unsigned acpi_adr_t_to_f(unsigned art)
335 {
336   switch (art)
337     {
338     case ACPI_MEMORY_RANGE: return Resource::Mmio_res;
339     case ACPI_IO_RANGE: return Resource::Io_res;
340     case ACPI_BUS_NUMBER_RANGE: return Resource::Bus_res;
341     default: return ~0;
342     }
343 }
344
345 static void
346 acpi_adr_res(Hw::Device *host, ACPI_RESOURCE_ADDRESS const *ar, l4_uint64_t s, l4_uint64_t l,
347              bool qw)
348 {
349   unsigned flags = acpi_adr_t_to_f(ar->ResourceType)
350                    | Resource::F_fixed_size | Resource::F_fixed_addr;
351
352   if (flags == ~0U)
353     return;
354
355   if (qw)
356     flags |= Resource::F_width_64bit;
357
358   Resource *r;
359   if (ar->ProducerConsumer == ACPI_PRODUCER)
360     r = new Adr_resource_provider(flags, s, s + l - 1);
361   else
362     r = new Adr_resource(flags, s, s + l -1);
363
364   host->add_resource(r);
365 }
366
367 void
368 Acpi_res_discover::discover_crs(Hw::Device *host)
369 {
370   ACPI_BUFFER buf;
371   buf.Length = ACPI_ALLOCATE_BUFFER;
372
373   if (ACPI_FAILURE(AcpiGetCurrentResources(obj, &buf)))
374     return;
375
376   char const *p = (char const *)buf.Pointer;
377   while (p)
378     {
379       ACPI_RESOURCE const *r = (ACPI_RESOURCE const *)p;
380       ACPI_RESOURCE_DATA const *d = &r->Data;
381       unsigned flags = 0;
382
383       switch (r->Type)
384         {
385         case ACPI_RESOURCE_TYPE_END_TAG:
386           AcpiOsFree(buf.Pointer);
387           return;
388
389         case ACPI_RESOURCE_TYPE_IRQ:
390           flags = Resource::Irq_res;
391           flags |= (!d->Irq.Triggering) * Resource::Irq_info_base;
392           flags |= (!!d->Irq.Polarity) * Resource::Irq_info_base * 2;
393           for (unsigned c = 0; c < d->Irq.InterruptCount; ++c)
394             host->add_resource(new Adr_resource(flags, d->Irq.Interrupts[c],
395                                                 d->Irq.Interrupts[c]));
396           break;
397
398         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
399           flags = Resource::Irq_res;
400           flags |= (!d->ExtendedIrq.Triggering) * Resource::Irq_info_base;
401           flags |= (!!d->ExtendedIrq.Polarity) * Resource::Irq_info_base * 2;
402           if (d->ExtendedIrq.ResourceSource.StringPtr)
403             {
404               d_printf(DBG_DEBUG2, "hoo indirect IRQ resource found src=%s idx=%d\n",
405                       d->ExtendedIrq.ResourceSource.StringPtr,
406                       d->ExtendedIrq.ResourceSource.Index);
407             }
408           else
409             {
410               for (unsigned c = 0; c < d->ExtendedIrq.InterruptCount; ++c)
411                 host->add_resource(new Adr_resource(flags, d->ExtendedIrq.Interrupts[c],
412                       d->ExtendedIrq.Interrupts[c]));
413             }
414           break;
415
416         case ACPI_RESOURCE_TYPE_IO:
417           flags = Resource::Io_res | Resource::F_fixed_size | Resource::F_fixed_addr;
418           host->add_resource(new Adr_resource(flags, d->Io.Minimum,
419                                               d->Io.Minimum + d->Io.AddressLength - 1));
420           break;
421
422         case ACPI_RESOURCE_TYPE_FIXED_IO:
423           flags = Resource::Io_res | Resource::F_fixed_size | Resource::F_fixed_addr;
424           host->add_resource(new Adr_resource(flags, d->FixedIo.Address,
425                                               d->FixedIo.Address + d->FixedIo.AddressLength - 1));
426           break;
427
428         case ACPI_RESOURCE_TYPE_MEMORY24:
429           flags = Resource::Mmio_res | Resource::F_fixed_size | Resource::F_fixed_addr;
430           host->add_resource(new Adr_resource(flags, d->Memory24.Minimum,
431                                               d->Memory24.Minimum + d->Memory24.AddressLength - 1));
432           break;
433
434         case ACPI_RESOURCE_TYPE_MEMORY32:
435           flags = Resource::Mmio_res | Resource::F_fixed_size | Resource::F_fixed_addr;
436           host->add_resource(new Adr_resource(flags, d->Memory32.Minimum,
437                                               d->Memory32.Minimum + d->Memory32.AddressLength - 1));
438           break;
439
440         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
441           flags = Resource::Mmio_res | Resource::F_fixed_size | Resource::F_fixed_addr;
442           host->add_resource(new Adr_resource(flags, d->FixedMemory32.Address,
443                                d->FixedMemory32.Address + d->FixedMemory32.AddressLength - 1));
444           break;
445
446         case ACPI_RESOURCE_TYPE_ADDRESS16:
447           acpi_adr_res(host, &d->Address, d->Address16.Minimum, d->Address16.AddressLength, 0);
448           break;
449
450         case ACPI_RESOURCE_TYPE_ADDRESS32:
451           acpi_adr_res(host, &d->Address, d->Address32.Minimum, d->Address32.AddressLength, 0);
452           break;
453
454         case ACPI_RESOURCE_TYPE_ADDRESS64:
455           acpi_adr_res(host, &d->Address, d->Address64.Minimum, d->Address64.AddressLength, 1);
456           break;
457
458         default:
459           d_printf(DBG_WARN, "WARNING: ignoring ACPI recource (unkown type: %d)\n", r->Type);
460           break;
461
462
463         }
464
465       p += r->Length;
466     }
467
468   AcpiOsFree(buf.Pointer);
469 }
470
471 void
472 Acpi_res_discover::discover_resources(Hw::Device *host)
473 {
474   Pci_bridge *bridge = dynamic_cast<Pci_bridge*>(host->discover_bus_if());
475   if (bridge)
476     discover_prt(host);
477
478   discover_crs(host);
479
480   if (bridge)
481     {
482       for (Resource_list::iterator i = host->resources()->begin();
483           i != host->resources()->end(); ++i)
484         {
485           if ((*i)->type() == Resource::Bus_res)
486             bridge->num = bridge->subordinate = static_cast<Adr_resource*>(*i)->start();
487         }
488     }
489 }
490
491
492 static l4_uint32_t
493 get_adr(ACPI_HANDLE dev)
494 {
495   ACPI_HANDLE adr;
496   if (ACPI_FAILURE(AcpiGetHandle(dev, const_cast<char*>("_ADR"), &adr)))
497     return ~0U;
498
499   ACPI_OBJECT adro;
500   ACPI_BUFFER ret_buf;
501   ret_buf.Pointer = &adro;
502   ret_buf.Length = sizeof(adro);
503   if (ACPI_SUCCESS(AcpiEvaluateObject(adr, NULL, NULL, &ret_buf)))
504     {
505       switch (adro.Type)
506         {
507         case ACPI_TYPE_INTEGER:
508           return adro.Integer.Value;
509         default:
510           return ~0;
511         }
512     }
513
514   return ~0;
515 }
516
517 static void
518 get_name(ACPI_HANDLE dev, Hw::Device *hd)
519 {
520   char str[5];
521   ACPI_BUFFER buf;
522   buf.Pointer = &str;
523   buf.Length = sizeof(str);
524   if (ACPI_SUCCESS(AcpiGetName(dev, ACPI_SINGLE_NAME, &buf)))
525     hd->set_name(str);
526 }
527
528
529 static ACPI_STATUS
530 discover_pre_cb(ACPI_HANDLE obj, UINT32 nl, void *ctxt, void **)
531 {
532   Discover_ctxt *c = reinterpret_cast<Discover_ctxt*>(ctxt);
533
534   if (nl == 1)
535     return AE_OK;
536
537   if (nl > c->level)
538     {
539       c->current_bus = c->last_device;
540       c->level = nl;
541     }
542
543   l4_uint32_t adr = get_adr(obj);
544
545   Hw::Device *nd = c->current_bus->get_child_dev_uid((l4_umword_t)obj, adr, true);
546   c->last_device = nd;
547
548   get_name(obj, nd);
549
550   ACPI_DEVICE_ID *hid = 0;
551   ACPI_DEVICE_ID_LIST *cid = 0;
552   bool pci_rb = false;
553 #if 0
554   if (ACPI_FAILURE(AcpiUtAcquireMutex(ACPI_MTX_NAMESPACE)))
555     return AE_OK;
556 #endif
557
558   ACPI_NAMESPACE_NODE *node = AcpiNsValidateHandle(obj);
559   if (!node)
560     {
561       //AcpiUtReleaseMutex(ACPI_MTX_NAMESPACE);
562       return AE_OK;
563     }
564
565   if (ACPI_SUCCESS(AcpiUtExecute_HID(node, &hid)))
566     {
567       nd->set_hid(hid->String);
568       pci_rb |= AcpiUtIsPciRootBridge(hid->String);
569       ACPI_FREE(hid);
570     }
571
572   if (ACPI_SUCCESS(AcpiUtExecute_CID(node, &cid)))
573     {
574       for (unsigned i = 0; i < cid->Count; ++i)
575         {
576           nd->add_cid(cid->Ids[i].String);
577           pci_rb |= AcpiUtIsPciRootBridge(cid->Ids[i].String);
578         }
579       ACPI_FREE(cid);
580     }
581
582
583   //AcpiUtReleaseMutex(ACPI_MTX_NAMESPACE);
584
585   // hm, this seems very specific for PCI
586   if (pci_rb)
587     {
588       d_printf(DBG_DEBUG, "Found PCI root bridge...\n");
589       if (Pci_root_bridge *rb = pci_root_bridge(0))
590         {
591           if (rb->host())
592             {
593               // we found a second root bridge
594               // create a new root pridge instance
595               rb = new Pci_port_root_bridge(-1, nd);
596             }
597           else
598             rb->set_host(nd);
599
600           nd->set_discover_bus_if(rb);
601         }
602       else
603         d_printf(DBG_ERR, "ERROR: there is no PCI bus driver for this platform\n");
604     }
605
606   nd->add_resource_discoverer(new Acpi_res_discover(obj));
607
608   return AE_OK;
609 }
610
611 static ACPI_STATUS
612 discover_post_cb(ACPI_HANDLE, UINT32 nl, void *ctxt, void **)
613 {
614   Discover_ctxt *c = reinterpret_cast<Discover_ctxt*>(ctxt);
615   if (nl < c->level)
616     {
617       c->level = nl;
618       c->current_bus = c->current_bus->parent();
619     }
620   return AE_OK;
621 }
622
623 }
624
625
626 int acpica_init()
627 {
628   d_printf(DBG_INFO, "Hello from L4-ACPICA\n");
629
630   pci_register_root_bridge(0, new Pci_port_root_bridge(0, 0));
631
632   AcpiDbgLevel =
633       ACPI_LV_INIT
634     //| ACPI_LV_INFO
635    // | ACPI_LV_FUNCTIONSkern/irq.cpp
636    //     | ACPI_LV_ALL_EXCEPTIONS 
637     //    | ACPI_LV_LOAD 
638     //    | ACPI_LV_INIT_NAMES 
639         | ACPI_LV_TABLES 
640     //    | ACPI_LV_RESOURCES 
641     //    | ACPI_LV_NAMES
642     //    | ACPI_LV_VALUES 
643     //    | ACPI_LV_OPREGION  
644         | ACPI_LV_VERBOSE_INFO 
645     //    | ACPI_LV_PARSE
646     //    | ACPI_LV_DISPATCH
647     //    | ACPI_LV_EXEC
648     //    | ACPI_LV_IO
649     ;
650
651 //0. enable workarounds, see include/acglobals.h
652   AcpiGbl_EnableInterpreterSlack = (1==1);
653   ACPI_STATUS status;
654
655   status = AcpiInitializeSubsystem();
656   if(status!=AE_OK)
657     return status;
658
659   status = AcpiInitializeTables (0, 0, TRUE);
660   if(status!=AE_OK)
661     return status;
662
663   status = AcpiReallocateRootTable ();
664 //  if(status!=AE_OK)
665 //    return status;
666
667   status = AcpiLoadTables ();
668
669   if(ACPI_FAILURE(status))
670     return status;
671
672   d_printf(DBG_DEBUG, "enable ACPI subsystem\n");
673   status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
674
675   if (ACPI_FAILURE(status))
676     {
677       d_printf(DBG_ERR, "Unable to start the ACPI Interpreter\n");
678       exit(status);
679     }
680
681   d_printf(DBG_DEBUG, "initialize ACPI objects\n");
682   status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
683   if (ACPI_FAILURE(status)) {
684       d_printf(DBG_ERR, "Unable to initialize ACPI objects\n");
685       exit(status);
686   }
687
688   d_printf(DBG_DEBUG, "Interpreter enabled\n");
689
690   Discover_ctxt c;
691   c.last_device = system_bus();
692   c.current_bus = system_bus();
693   c.level = 1;
694
695
696   d_printf(DBG_DEBUG, "scanning for PCI root bridge\n");
697   status = AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
698                              ACPI_UINT32_MAX,
699                              discover_pre_cb, discover_post_cb, &c, 0);
700
701   /*
702    * Get the system interrupt model and evaluate \_PIC.
703    */
704   int result = acpi_bus_init_irq();
705   if (result)
706     {
707       d_printf(DBG_ERR, "Could not initialize ACPI IRQ stuff\n");
708       exit(1);
709     }
710   status = AcpiSubsystemStatus();
711
712   if (ACPI_FAILURE(status))
713       exit(status);
714
715   d_printf(DBG_INFO, "ACPI subsystem initialized\n");
716
717   ACPI_BUFFER ret_buffer;
718   ret_buffer.Length = ACPI_ALLOCATE_BUFFER;
719
720   status = AcpiGetSystemInfo(&ret_buffer);
721
722   if(ACPI_FAILURE(status))
723     exit(status);
724
725   acpi_print_system_info(ret_buffer.Pointer);
726
727   AcpiOsFree(ret_buffer.Pointer);
728
729   return 0;
730 }
731