Re: acpi_call crash fix
Aaron LI <[email protected]> Thu, 12 Dec 2019 21:49:38 +0800
| Newsgroups | gmane.os.dragonfly-bsd.kernel |
|---|---|
| Message-ID | <[email protected]> |
On December 12, 2019 4:42:18 AM GMT+08:00, K Staring <qdk@quickdekay=2Enet>=
wrote:
>Hi,
>
>Another one=2E=2E While using acpi_call to disable the dGPU on my Dell XP=
S
>9560,
>I experienced a crash=2E FreeBSD had fixed this exact crash some months
>prior;
>included is a patch which imports the fix=2E
>
>
>Regards,
>
>Khamba
>
>
>--- a/sys/dev/acpica/acpi=2Ec
>+++ b/sys/dev/acpica/acpi=2Ec
>@@ -300,7 +300,7 @@ SYSCTL_INT(_debug_acpi, OID_AUTO, do_powerstate,
>CTLFLAG_RW,
> TUNABLE_INT("debug=2Eacpi=2Equirks", &acpi_quirks);
>=20
> /* Allow to call ACPI methods from userland=2E */
>-static int acpi_allow_mcall;
>+static int acpi_allow_mcall =3D 0;
> TUNABLE_INT("debug=2Eacpi=2Eallow_method_calls", &acpi_allow_mcall);
>=20
> static int acpi_susp_bounce;
>@@ -3230,6 +3230,136 @@ acpiclose(struct dev_close_args *ap)
> return (0);
> }
>=20
>+//----------------------------------------------------------------------=
----
>+void acpi_call_fixup_pointers(ACPI_OBJECT *p, UINT8 *orig);
>+
>+static void
>+free_acpi_object_list(ACPI_OBJECT_LIST *list)
>+{
>+ for (int i =3D 0; i < list->Count; i++) {
>+ switch (list->Pointer[i]=2EType) {
>+ case ACPI_TYPE_STRING:
>+ AcpiOsFree(list->Pointer[i]=2EString=2EPointer);
>+ break;
>+ case ACPI_TYPE_BUFFER:
>+ AcpiOsFree(list->Pointer[i]=2EBuffer=2EPointer);
>+ break;
>+ default:
>+ break;
>+ }
>+ }
>+ AcpiOsFree(list);
>+}
>+
>+static ACPI_OBJECT_LIST *
>+copyin_acpi_object_list(ACPI_OBJECT_LIST *src)
>+{
>+ ACPI_OBJECT_LIST *dest;
>+ bool failed;
>+
>+ if (src->Count > 7)
>+ return NULL;
>+
>+ dest =3D AcpiOsAllocate(sizeof(ACPI_OBJECT_LIST) + sizeof(ACPI_OBJECT)
>* src->Count);
>+ if (!dest)
>+ return NULL;
>+
>+ dest->Count =3D src->Count;
>+ dest->Pointer =3D (ACPI_OBJECT *)(dest + 1);
>+ if (copyin(src->Pointer, dest->Pointer, sizeof(ACPI_OBJECT) *
>dest->Count)) {
>+ AcpiOsFree(dest);
>+ return NULL;
>+ }
>+
>+ failed =3D false;
>+
>+ for (int i =3D 0; i < dest->Count; i++) {
>+ switch (dest->Pointer[i]=2EType) {
>+ case ACPI_TYPE_INTEGER:
>+ break;
>+ case ACPI_TYPE_STRING: {
>+ void *v =3D AcpiOsAllocate(dest->Pointer[i]=2EString=2ELength);
>+ if (!v || copyin(dest->Pointer[i]=2EString=2EPointer, v,
>dest->Pointer[i]=2EString=2ELength))
>+ failed =3D true;
>+ dest->Pointer[i]=2EString=2EPointer =3D v;
>+ break;
>+ }
>+ case ACPI_TYPE_BUFFER: {
>+ void *v =3D AcpiOsAllocate(dest->Pointer[i]=2EBuffer=2ELength);
>+ if (!v || copyin(dest->Pointer[i]=2EBuffer=2EPointer, v,
>dest->Pointer[i]=2EBuffer=2ELength))
>+ failed =3D true;
>+ dest->Pointer[i]=2EString=2EPointer =3D v;
>+ break;
>+ }
>+ default:
>+ failed =3D true;
>+ break;
>+ }
>+ }
>+
>+ if (failed) {
>+ free_acpi_object_list(dest);
>+ dest =3D NULL;
>+ }
>+
>+ return dest;
>+}
>+
>+static int
>+acpi_call_ioctl(caddr_t addr)
>+{
>+ struct acpi_mcall_ioctl_arg *params;
>+ ACPI_OBJECT_LIST *args;
>+ ACPI_BUFFER result;
>+ char path[256];
>+
>+ result=2ELength =3D ACPI_ALLOCATE_BUFFER;
>+ result=2EPointer =3D NULL;
>+
>+ params =3D (struct acpi_mcall_ioctl_arg*)addr;
>+ args =3D copyin_acpi_object_list(¶ms->args);
>+ if (!args)
>+ return EINVAL;
>+ if (copyinstr(params->path, path, sizeof(path), NULL))
>+ return EINVAL;
>+ params->retval =3D AcpiEvaluateObject(NULL, path, args, &result);
>+ if (ACPI_SUCCESS(params->retval))
>+ {
>+ if (result=2EPointer !=3D NULL)
>+ {
>+ if (params->result=2EPointer !=3D NULL)
>+ {=09
>+ params->result=2ELength =3D min(params->result=2ELength, result=2ELe=
ngth);
>+ if (result=2ELength >=3D sizeof(ACPI_OBJECT))
>+ acpi_call_fixup_pointers((ACPI_OBJECT*)result=2EPointer,
>params->result=2EPointer);
>+ copyout(result=2EPointer, params->result=2EPointer,
>+ params->result=2ELength);
>+ params->reslen =3D result=2ELength;
>+ }
>+ AcpiOsFree(result=2EPointer);
>+ }
>+ }
>+ free_acpi_object_list(args);
>+
>+ return (0);
>+}
>+
>+void
>+acpi_call_fixup_pointers(ACPI_OBJECT *p, UINT8 *dest)
>+{
>+ switch (p->Type)
>+ {
>+ case ACPI_TYPE_STRING:
>+ p->String=2EPointer +=3D dest - (UINT8*)p;
>+ break;
>+ case ACPI_TYPE_BUFFER:
>+ p->Buffer=2EPointer +=3D dest - (UINT8*)p;
>+ break;
>+ }
>+}
>+
>+//----------------------------------------------------------------------=
----
>+
> static int
> acpiioctl(struct dev_ioctl_args *ap)
> {
>@@ -3297,40 +3427,7 @@ acpiioctl(struct dev_ioctl_args *ap)
> break;
> case ACPIIO_DO_MCALL:
> if (acpi_allow_mcall =3D=3D 1) {
>- struct acpi_mcall_ioctl_arg *params;
>- ACPI_BUFFER result =3D { ACPI_ALLOCATE_BUFFER, NULL };
>- ACPI_OBJECT *resobj;
>-
>- error =3D EINVAL;
>- params =3D (struct acpi_mcall_ioctl_arg *)ap->a_data;
>- params->retval =3D AcpiEvaluateObject(NULL, params->path,
>- ¶ms->args, &result);
>- if (ACPI_SUCCESS(params->retval) && result=2EPointer !=3D NULL &&
>- params->result=2EPointer !=3D NULL) {
>- params->result=2ELength =3D min(params->result=2ELength,
>- result=2ELength);
>- copyout(result=2EPointer, params->result=2EPointer,
>- params->result=2ELength);
>- params->reslen =3D result=2ELength;
>- if (result=2ELength >=3D sizeof(ACPI_OBJECT)) {
>- resobj =3D (ACPI_OBJECT *)params->result=2EPointer;
>- switch (resobj->Type) {
>- case ACPI_TYPE_STRING:
>- resobj->String=2EPointer =3D (char *)
>- ((UINT8 *)(resobj->String=2EPointer) -
>- (UINT8 *)result=2EPointer +
>- (UINT8 *)resobj);
>- break;
>- case ACPI_TYPE_BUFFER:
>- resobj->Buffer=2EPointer -=3D (UINT8 *)result=2EPointer -
>- (UINT8 *)resobj;
>- break;
>- }
>- }
>- error =3D 0;
>- }
>- if (result=2EPointer !=3D NULL)
>- AcpiOsFree(result=2EPointer);
>+ error =3D acpi_call_ioctl(ap->a_data);
> } else {
> device_printf(sc->acpi_dev,
> "debug=2Eacpi=2Eallow_method_calls must be set\n");
Hi, thank you very much for providing the nice patch=2E We've merged it in=
to the master and release branches=2E
Regards,
--=20
Aaron