1 /*- 2 * Copyright (c) 2003 Nate Lawson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/sys/dev/acpica/acpi_package.c,v 1.9.8.1 2009/04/15 03:14:26 kensmith Exp $ 27 */ 28 29 #include <sys/param.h> 30 #include <sys/kernel.h> 31 #include <sys/bus.h> 32 #include <sys/sbuf.h> 33 34 #include <sys/rman.h> 35 36 #include "acpi.h" 37 #include <dev/acpica/acpivar.h> 38 39 /* 40 * Package manipulation convenience functions 41 */ 42 43 int 44 acpi_PkgInt(ACPI_OBJECT *res, int idx, UINT64 *dst) 45 { 46 ACPI_OBJECT *obj; 47 48 obj = &res->Package.Elements[idx]; 49 if (obj == NULL || obj->Type != ACPI_TYPE_INTEGER) 50 return (EINVAL); 51 *dst = obj->Integer.Value; 52 53 return (0); 54 } 55 56 int 57 acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst) 58 { 59 UINT64 tmp; 60 int error; 61 62 error = acpi_PkgInt(res, idx, &tmp); 63 if (error == 0) 64 *dst = (uint32_t)tmp; 65 66 return (error); 67 } 68 69 int 70 acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size) 71 { 72 ACPI_OBJECT *obj; 73 void *ptr; 74 size_t length; 75 76 obj = &res->Package.Elements[idx]; 77 if (obj == NULL) 78 return (EINVAL); 79 bzero(dst, size); 80 81 switch (obj->Type) { 82 case ACPI_TYPE_STRING: 83 ptr = obj->String.Pointer; 84 length = obj->String.Length; 85 break; 86 case ACPI_TYPE_BUFFER: 87 ptr = obj->Buffer.Pointer; 88 length = obj->Buffer.Length; 89 break; 90 default: 91 return (EINVAL); 92 } 93 94 /* Make sure string will fit, including terminating NUL */ 95 if (++length > size) 96 return (E2BIG); 97 98 strlcpy(dst, ptr, length); 99 return (0); 100 } 101 102 int 103 acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type, int *rid, 104 struct resource **dst, u_int flags) 105 { 106 ACPI_GENERIC_ADDRESS gas; 107 ACPI_OBJECT *obj; 108 109 obj = &res->Package.Elements[idx]; 110 if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER || 111 obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3) 112 return (EINVAL); 113 114 memcpy(&gas, obj->Buffer.Pointer + 3, sizeof(gas)); 115 116 return (acpi_bus_alloc_gas(dev, type, rid, &gas, dst, flags)); 117 } 118 119 int 120 acpi_PkgRawGas(ACPI_OBJECT *res, int idx, ACPI_GENERIC_ADDRESS *gas) 121 { 122 ACPI_OBJECT *obj; 123 obj = &res->Package.Elements[idx]; 124 if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER || 125 obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3) 126 return (EINVAL); 127 memcpy(gas, obj->Buffer.Pointer + 3, sizeof(*gas)); 128 return (0); 129 } 130 131 ACPI_HANDLE 132 acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj) 133 { 134 ACPI_HANDLE h; 135 136 if (obj == NULL) 137 return (NULL); 138 139 switch (obj->Type) { 140 case ACPI_TYPE_LOCAL_REFERENCE: 141 case ACPI_TYPE_ANY: 142 h = obj->Reference.Handle; 143 break; 144 case ACPI_TYPE_STRING: 145 /* 146 * The String object usually contains a fully-qualified path, so 147 * scope can be NULL. 148 * 149 * XXX This may not always be the case. 150 */ 151 if (ACPI_FAILURE(AcpiGetHandle(scope, obj->String.Pointer, &h))) 152 h = NULL; 153 break; 154 default: 155 h = NULL; 156 break; 157 } 158 159 return (h); 160 } 161