Re: [PATCH v3 gnumach] ACPI: Support XSDT (ACPI >= v2.0)
Applied, thanks! Damien Zammit, le mer. 31 janv. 2024 02:12:26 +, a ecrit: > This enables gnumach to additionally parse the XSDT table > if the revision of ACPI is 2. > > TESTED: Still works on qemu (ACPI v1.0) > TESTED: Works on a x86 board with XSDT (ACPI v2.0) > --- > i386/i386at/acpi_parse_apic.c | 258 ++ > i386/i386at/acpi_parse_apic.h | 18 ++- > i386/i386at/model_dep.c | 8 +- > 3 files changed, 195 insertions(+), 89 deletions(-) > > diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c > index 1aef53ed..dcd5da89 100644 > --- a/i386/i386at/acpi_parse_apic.c > +++ b/i386/i386at/acpi_parse_apic.c > @@ -43,13 +43,12 @@ unsigned lapic_addr; > * and the number of entries stored in RSDT. > */ > void > -acpi_print_info(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, int > acpi_rsdt_n) > +acpi_print_info(phys_addr_t rsdp, void *rsdt, int acpi_rsdt_n) > { > > printf("ACPI:\n"); > -printf(" rsdp = %p; rsdp->rsdt_addr = %x\n", rsdp, rsdp->rsdt_addr); > -printf(" rsdt = %p; rsdt->length = %x (n = %x)\n", rsdt, > rsdt->header.length, > - acpi_rsdt_n); > +printf(" rsdp = 0x%lx\n", rsdp); > +printf(" rsdt/xsdt = 0x%p (n = %d)\n", rsdt, acpi_rsdt_n); > } > > /* > @@ -99,27 +98,45 @@ acpi_check_signature(const uint8_t table_signature[], > const char *real_signature > * > * Preconditions: RSDP pointer must not be NULL. > * > - * Returns 0 if correct. > + * Returns 1 if ACPI 1.0 and sets sdt_base > + * Returns 2 if ACPI >= 2.0 and sets sdt_base > */ > static int8_t > -acpi_check_rsdp(struct acpi_rsdp *rsdp) > +acpi_check_rsdp(struct acpi_rsdp2 *rsdp, phys_addr_t *sdt_base) > { > -uint32_t checksum; > int is_rsdp; > +uint8_t cksum; > > /* Check if rsdp signature match with the ACPI RSDP signature. */ > -is_rsdp = acpi_check_signature(rsdp->signature, ACPI_RSDP_SIG, > 8*sizeof(uint8_t)); > +is_rsdp = acpi_check_signature(rsdp->v1.signature, ACPI_RSDP_SIG, > 8*sizeof(uint8_t)); > > if (is_rsdp != ACPI_SUCCESS) > return ACPI_BAD_SIGNATURE; > > -/* If match, calculates rdsp checksum and check It. */ > -checksum = acpi_checksum(rsdp, sizeof(struct acpi_rsdp)); > +if (rsdp->v1.revision == 0) { > +// ACPI 1.0 > +*sdt_base = rsdp->v1.rsdt_addr; > +printf("ACPI v1.0\n"); > +cksum = acpi_checksum((void *)(>v1), sizeof(struct acpi_rsdp)); > > -if (checksum != 0) > -return ACPI_BAD_CHECKSUM; > +if (cksum != 0) > +return ACPI_BAD_CHECKSUM; > > -return ACPI_SUCCESS; > +return 1; > + > +} else if (rsdp->v1.revision == 2) { > +// ACPI >= 2.0 > +*sdt_base = rsdp->xsdt_addr; > +printf("ACPI >= v2.0\n"); > +cksum = acpi_checksum((void *)rsdp, sizeof(struct acpi_rsdp2)); > + > +if (cksum != 0) > +return ACPI_BAD_CHECKSUM; > + > +return 2; > +} > + > +return ACPI_NO_RSDP; > } > > /* > @@ -147,38 +164,41 @@ acpi_check_rsdp_align(void *addr) > * > * Preconditions: The start address (addr) must be aligned. > * > - * Returns the reference to rsdp structure if success, NULL if failure. > + * Returns the physical address of rsdp structure if success, 0 if failure. > */ > -static struct acpi_rsdp* > -acpi_search_rsdp(void *addr, uint32_t length) > +static phys_addr_t > +acpi_search_rsdp(void *addr, uint32_t length, int *is_64bit) > { > void *end; > +int version = 0; > +phys_addr_t sdt_base = 0; > > /* Search RDSP in memory space between addr and addr+lenght. */ > for (end = addr+length; addr < end; addr += ACPI_RSDP_ALIGN) { > > /* Check if the current memory block stores the RDSP. */ > -if ((addr != NULL) && (acpi_check_rsdp(addr) == ACPI_SUCCESS)) { > -/* If yes, return RSDP address */ > -return (struct acpi_rsdp*) addr; > +if ((addr != NULL) && ((version = acpi_check_rsdp(addr, _base)) > > 0)) { > +/* If yes, return RSDT/XSDT address */ > +*is_64bit = (version == 2); > +return sdt_base; > } > } > > -return NULL; > +return 0; > } > > /* > * acpi_get_rsdp: tries to find the RSDP table, > * searching It in many memory ranges, as It's written in ACPI Specification. > * > - * Returns the reference to RDSP structure if success, NULL if failure. > + * Returns the reference to RDSP structure if success, 0 if failure. > */ > -static struct acpi_rsdp* > -acpi_get_rsdp(void) > +static phys_addr_t > +acpi_get_rsdp(int *is_64bit) > { > uint16_t *start = 0; > phys_addr_t base = 0; > -struct acpi_rsdp *rsdp = NULL; > +phys_addr_t rsdp = 0; > > /* EDBA start address. */ > start = (uint16_t*) phystokv(0x040e); > @@ -186,40 +206,17 @@ acpi_get_rsdp(void) > > /* check alignment. */ > if (acpi_check_rsdp_align((void *)base) ==
[PATCH v3 gnumach] ACPI: Support XSDT (ACPI >= v2.0)
This enables gnumach to additionally parse the XSDT table if the revision of ACPI is 2. TESTED: Still works on qemu (ACPI v1.0) TESTED: Works on a x86 board with XSDT (ACPI v2.0) --- i386/i386at/acpi_parse_apic.c | 258 ++ i386/i386at/acpi_parse_apic.h | 18 ++- i386/i386at/model_dep.c | 8 +- 3 files changed, 195 insertions(+), 89 deletions(-) diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c index 1aef53ed..dcd5da89 100644 --- a/i386/i386at/acpi_parse_apic.c +++ b/i386/i386at/acpi_parse_apic.c @@ -43,13 +43,12 @@ unsigned lapic_addr; * and the number of entries stored in RSDT. */ void -acpi_print_info(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, int acpi_rsdt_n) +acpi_print_info(phys_addr_t rsdp, void *rsdt, int acpi_rsdt_n) { printf("ACPI:\n"); -printf(" rsdp = %p; rsdp->rsdt_addr = %x\n", rsdp, rsdp->rsdt_addr); -printf(" rsdt = %p; rsdt->length = %x (n = %x)\n", rsdt, rsdt->header.length, - acpi_rsdt_n); +printf(" rsdp = 0x%lx\n", rsdp); +printf(" rsdt/xsdt = 0x%p (n = %d)\n", rsdt, acpi_rsdt_n); } /* @@ -99,27 +98,45 @@ acpi_check_signature(const uint8_t table_signature[], const char *real_signature * * Preconditions: RSDP pointer must not be NULL. * - * Returns 0 if correct. + * Returns 1 if ACPI 1.0 and sets sdt_base + * Returns 2 if ACPI >= 2.0 and sets sdt_base */ static int8_t -acpi_check_rsdp(struct acpi_rsdp *rsdp) +acpi_check_rsdp(struct acpi_rsdp2 *rsdp, phys_addr_t *sdt_base) { -uint32_t checksum; int is_rsdp; +uint8_t cksum; /* Check if rsdp signature match with the ACPI RSDP signature. */ -is_rsdp = acpi_check_signature(rsdp->signature, ACPI_RSDP_SIG, 8*sizeof(uint8_t)); +is_rsdp = acpi_check_signature(rsdp->v1.signature, ACPI_RSDP_SIG, 8*sizeof(uint8_t)); if (is_rsdp != ACPI_SUCCESS) return ACPI_BAD_SIGNATURE; -/* If match, calculates rdsp checksum and check It. */ -checksum = acpi_checksum(rsdp, sizeof(struct acpi_rsdp)); +if (rsdp->v1.revision == 0) { +// ACPI 1.0 +*sdt_base = rsdp->v1.rsdt_addr; +printf("ACPI v1.0\n"); +cksum = acpi_checksum((void *)(>v1), sizeof(struct acpi_rsdp)); -if (checksum != 0) -return ACPI_BAD_CHECKSUM; +if (cksum != 0) +return ACPI_BAD_CHECKSUM; -return ACPI_SUCCESS; +return 1; + +} else if (rsdp->v1.revision == 2) { +// ACPI >= 2.0 +*sdt_base = rsdp->xsdt_addr; +printf("ACPI >= v2.0\n"); +cksum = acpi_checksum((void *)rsdp, sizeof(struct acpi_rsdp2)); + +if (cksum != 0) +return ACPI_BAD_CHECKSUM; + +return 2; +} + +return ACPI_NO_RSDP; } /* @@ -147,38 +164,41 @@ acpi_check_rsdp_align(void *addr) * * Preconditions: The start address (addr) must be aligned. * - * Returns the reference to rsdp structure if success, NULL if failure. + * Returns the physical address of rsdp structure if success, 0 if failure. */ -static struct acpi_rsdp* -acpi_search_rsdp(void *addr, uint32_t length) +static phys_addr_t +acpi_search_rsdp(void *addr, uint32_t length, int *is_64bit) { void *end; +int version = 0; +phys_addr_t sdt_base = 0; /* Search RDSP in memory space between addr and addr+lenght. */ for (end = addr+length; addr < end; addr += ACPI_RSDP_ALIGN) { /* Check if the current memory block stores the RDSP. */ -if ((addr != NULL) && (acpi_check_rsdp(addr) == ACPI_SUCCESS)) { -/* If yes, return RSDP address */ -return (struct acpi_rsdp*) addr; +if ((addr != NULL) && ((version = acpi_check_rsdp(addr, _base)) > 0)) { +/* If yes, return RSDT/XSDT address */ +*is_64bit = (version == 2); +return sdt_base; } } -return NULL; +return 0; } /* * acpi_get_rsdp: tries to find the RSDP table, * searching It in many memory ranges, as It's written in ACPI Specification. * - * Returns the reference to RDSP structure if success, NULL if failure. + * Returns the reference to RDSP structure if success, 0 if failure. */ -static struct acpi_rsdp* -acpi_get_rsdp(void) +static phys_addr_t +acpi_get_rsdp(int *is_64bit) { uint16_t *start = 0; phys_addr_t base = 0; -struct acpi_rsdp *rsdp = NULL; +phys_addr_t rsdp = 0; /* EDBA start address. */ start = (uint16_t*) phystokv(0x040e); @@ -186,40 +206,17 @@ acpi_get_rsdp(void) /* check alignment. */ if (acpi_check_rsdp_align((void *)base) == ACPI_BAD_ALIGN) -return NULL; -rsdp = acpi_search_rsdp((void *)base, 1024); +return 0; +rsdp = acpi_search_rsdp((void *)base, 1024, is_64bit); -if (rsdp == NULL) { +if (rsdp == 0) { /* If RSDP isn't in EDBA, search in the BIOS read-only memory space between 0Eh and 0Fh */ -rsdp = acpi_search_rsdp((void
Re: [PATCH v2 gnumach] ACPI: Support XSDT (ACPI >= v2.0)
Damien Zammit, le mar. 30 janv. 2024 08:04:38 +, a ecrit: > This enables gnumach to additionally parse the XSDT table > if the revision of ACPI is 2. > > NB: I removed a few checksum checks in acpi tables where > there is no checksum present in the table. > > TESTED: Still works on qemu (ACPI v1.0) > TESTED: Works on a x86 board with XSDT (ACPI v2.0) > > --- > i386/i386at/acpi_parse_apic.c | 243 ++ > i386/i386at/acpi_parse_apic.h | 18 ++- > i386/i386at/model_dep.c | 8 +- > 3 files changed, 180 insertions(+), 89 deletions(-) > > diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c > index 1aef53ed..476d846e 100644 > --- a/i386/i386at/acpi_parse_apic.c > +++ b/i386/i386at/acpi_parse_apic.c > @@ -43,13 +43,12 @@ unsigned lapic_addr; > * and the number of entries stored in RSDT. > */ > void > -acpi_print_info(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, int > acpi_rsdt_n) > +acpi_print_info(phys_addr_t rsdp, void *rsdt, int acpi_rsdt_n) > { > > printf("ACPI:\n"); > -printf(" rsdp = %p; rsdp->rsdt_addr = %x\n", rsdp, rsdp->rsdt_addr); > -printf(" rsdt = %p; rsdt->length = %x (n = %x)\n", rsdt, > rsdt->header.length, > - acpi_rsdt_n); > +printf(" rsdp = 0x%lx\n", rsdp); > +printf(" rsdt/xsdt = 0x%p (n = %d)\n", rsdt, acpi_rsdt_n); > } > > /* > @@ -69,6 +68,8 @@ acpi_checksum(void *addr, uint32_t length) > for (i = 0; i < length; i++) > checksum += bytes[i]; > > +printf("checksum result = 0x%x\n", checksum); leftover ;) > return checksum; > } > > -/* > - * acpi_check_rsdt: check if the RSDT initial address is correct > - * checking its checksum. > - * > - * Receives as input a reference for the RSDT "candidate" table. > - * Returns 0 if success. > - * > - * Preconditions: rsdp must not be NULL. > - * > - */ > -static int > -acpi_check_rsdt(struct acpi_rsdt *rsdt) > -{ > -uint8_t checksum; > - > -checksum = acpi_checksum(rsdt, rsdt->header.length); > - > -if (checksum != 0) > -return ACPI_BAD_CHECKSUM; > - > -return ACPI_SUCCESS; > -} Don't we want to keep checking the rsdt checksum? > @@ -264,6 +253,40 @@ acpi_get_rsdt(struct acpi_rsdp *rsdp, int* acpi_rsdt_n) > return rsdt; > } > > +/* > + * acpi_get_xsdt: Get XSDT table reference from RSDPv2 entries. > + * > + * Receives as input a reference for RSDPv2 table > + * and a reference to store the number of entries of XSDT. > + * > + * Returns the reference to XSDT table if success, NULL if error. > + */ > +static struct acpi_xsdt* > +acpi_get_xsdt(phys_addr_t rsdp_phys, int* acpi_xsdt_n) > +{ > +struct acpi_xsdt *xsdt = NULL; > +int signature_check; > + > +xsdt = (struct acpi_xsdt*) kmem_map_aligned_table(rsdp_phys, > sizeof(struct acpi_xsdt), VM_PROT_READ); > + > +/* Check if the RSDT mapping is fine. */ > +if (xsdt == NULL) > +return NULL; > + > +/* Check is rsdt signature is equals to ACPI RSDT signature. */ > +signature_check = acpi_check_signature(xsdt->header.signature, > ACPI_XSDT_SIG, > + 4*sizeof(uint8_t)); > + > +if (signature_check != ACPI_SUCCESS) > +return NULL; Probably this table has a checksum too? > +/* Calculated number of elements stored in rsdt. */ > +*acpi_xsdt_n = (xsdt->header.length - sizeof(xsdt->header)) > + / sizeof(xsdt->entry[0]); > + > +return xsdt; > +} > + > /* > * acpi_get_apic: get MADT/APIC table from RSDT entries. > * > @@ -452,16 +512,9 @@ acpi_apic_parse_table(struct acpi_apic *apic) > static int > acpi_apic_setup(struct acpi_apic *apic) > { > -int apic_checksum; > ApicLocalUnit* lapic_unit; > uint8_t ncpus, nioapics; > > -/* Check the checksum of the APIC */ > -apic_checksum = acpi_checksum(apic, apic->header.length); > - > -if(apic_checksum != 0) > -return ACPI_BAD_CHECKSUM; > - And here as well, we'd want to keep the checksum? > /* map common lapic address */ > lapic_addr = apic->lapic_addr; > lapic_unit = kmem_map_aligned_table(apic->lapic_addr, > sizeof(ApicLocalUnit), Samuel
[PATCH v2 gnumach] ACPI: Support XSDT (ACPI >= v2.0)
This enables gnumach to additionally parse the XSDT table if the revision of ACPI is 2. NB: I removed a few checksum checks in acpi tables where there is no checksum present in the table. TESTED: Still works on qemu (ACPI v1.0) TESTED: Works on a x86 board with XSDT (ACPI v2.0) --- i386/i386at/acpi_parse_apic.c | 243 ++ i386/i386at/acpi_parse_apic.h | 18 ++- i386/i386at/model_dep.c | 8 +- 3 files changed, 180 insertions(+), 89 deletions(-) diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c index 1aef53ed..476d846e 100644 --- a/i386/i386at/acpi_parse_apic.c +++ b/i386/i386at/acpi_parse_apic.c @@ -43,13 +43,12 @@ unsigned lapic_addr; * and the number of entries stored in RSDT. */ void -acpi_print_info(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, int acpi_rsdt_n) +acpi_print_info(phys_addr_t rsdp, void *rsdt, int acpi_rsdt_n) { printf("ACPI:\n"); -printf(" rsdp = %p; rsdp->rsdt_addr = %x\n", rsdp, rsdp->rsdt_addr); -printf(" rsdt = %p; rsdt->length = %x (n = %x)\n", rsdt, rsdt->header.length, - acpi_rsdt_n); +printf(" rsdp = 0x%lx\n", rsdp); +printf(" rsdt/xsdt = 0x%p (n = %d)\n", rsdt, acpi_rsdt_n); } /* @@ -69,6 +68,8 @@ acpi_checksum(void *addr, uint32_t length) for (i = 0; i < length; i++) checksum += bytes[i]; +printf("checksum result = 0x%x\n", checksum); + return checksum; } @@ -99,27 +100,45 @@ acpi_check_signature(const uint8_t table_signature[], const char *real_signature * * Preconditions: RSDP pointer must not be NULL. * - * Returns 0 if correct. + * Returns 1 if ACPI 1.0 and sets sdt_base + * Returns 2 if ACPI >= 2.0 and sets sdt_base */ static int8_t -acpi_check_rsdp(struct acpi_rsdp *rsdp) +acpi_check_rsdp(struct acpi_rsdp2 *rsdp, phys_addr_t *sdt_base) { -uint32_t checksum; int is_rsdp; +uint8_t cksum; /* Check if rsdp signature match with the ACPI RSDP signature. */ -is_rsdp = acpi_check_signature(rsdp->signature, ACPI_RSDP_SIG, 8*sizeof(uint8_t)); +is_rsdp = acpi_check_signature(rsdp->v1.signature, ACPI_RSDP_SIG, 8*sizeof(uint8_t)); if (is_rsdp != ACPI_SUCCESS) return ACPI_BAD_SIGNATURE; -/* If match, calculates rdsp checksum and check It. */ -checksum = acpi_checksum(rsdp, sizeof(struct acpi_rsdp)); +if (rsdp->v1.revision == 0) { +// ACPI 1.0 +*sdt_base = rsdp->v1.rsdt_addr; +printf("ACPI v1.0\n"); +cksum = acpi_checksum((void *)(>v1), sizeof(struct acpi_rsdp)); -if (checksum != 0) -return ACPI_BAD_CHECKSUM; +if (cksum != 0) +return ACPI_BAD_CHECKSUM; -return ACPI_SUCCESS; +return 1; + +} else if (rsdp->v1.revision == 2) { +// ACPI >= 2.0 +*sdt_base = rsdp->xsdt_addr; +printf("ACPI >= v2.0\n"); +cksum = acpi_checksum((void *)rsdp, sizeof(struct acpi_rsdp2)); + +if (cksum != 0) +return ACPI_BAD_CHECKSUM; + +return 2; +} + +return ACPI_NO_RSDP; } /* @@ -147,38 +166,41 @@ acpi_check_rsdp_align(void *addr) * * Preconditions: The start address (addr) must be aligned. * - * Returns the reference to rsdp structure if success, NULL if failure. + * Returns the physical address of rsdp structure if success, 0 if failure. */ -static struct acpi_rsdp* -acpi_search_rsdp(void *addr, uint32_t length) +static phys_addr_t +acpi_search_rsdp(void *addr, uint32_t length, int *is_64bit) { void *end; +int version = 0; +phys_addr_t sdt_base = 0; /* Search RDSP in memory space between addr and addr+lenght. */ for (end = addr+length; addr < end; addr += ACPI_RSDP_ALIGN) { /* Check if the current memory block stores the RDSP. */ -if ((addr != NULL) && (acpi_check_rsdp(addr) == ACPI_SUCCESS)) { -/* If yes, return RSDP address */ -return (struct acpi_rsdp*) addr; +if ((addr != NULL) && ((version = acpi_check_rsdp(addr, _base)) > 0)) { +/* If yes, return RSDT/XSDT address */ +*is_64bit = (version == 2); +return sdt_base; } } -return NULL; +return 0; } /* * acpi_get_rsdp: tries to find the RSDP table, * searching It in many memory ranges, as It's written in ACPI Specification. * - * Returns the reference to RDSP structure if success, NULL if failure. + * Returns the reference to RDSP structure if success, 0 if failure. */ -static struct acpi_rsdp* -acpi_get_rsdp(void) +static phys_addr_t +acpi_get_rsdp(int *is_64bit) { uint16_t *start = 0; phys_addr_t base = 0; -struct acpi_rsdp *rsdp = NULL; +phys_addr_t rsdp = 0; /* EDBA start address. */ start = (uint16_t*) phystokv(0x040e); @@ -186,40 +208,17 @@ acpi_get_rsdp(void) /* check alignment. */ if (acpi_check_rsdp_align((void *)base) == ACPI_BAD_ALIGN) -return NULL; -rsdp =
Re: [PATCH 2/2 gnumach] ACPI: Support XSDT (ACPI >= v2.0)
Hello, Damien Zammit, le mer. 24 janv. 2024 03:52:03 +, a ecrit: > diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c > index 9cd861ed..7b377d33 100644 > --- a/i386/i386at/acpi_parse_apic.c > +++ b/i386/i386at/acpi_parse_apic.c > @@ -99,27 +98,33 @@ acpi_check_signature(const uint8_t table_signature[], > const char *real_signature > * > * Preconditions: RSDP pointer must not be NULL. > * > - * Returns 0 if correct. > + * Returns 1 if ACPI 1.0 and sets sdt_base > + * Returns 2 if ACPI >= 2.0 and sets sdt_base > */ > static int8_t > -acpi_check_rsdp(struct acpi_rsdp *rsdp) > +acpi_check_rsdp(struct acpi_rsdp2 *rsdp, phys_addr_t *sdt_base) > { > -uint32_t checksum; > int is_rsdp; > > /* Check if rsdp signature match with the ACPI RSDP signature. */ > -is_rsdp = acpi_check_signature(rsdp->signature, ACPI_RSDP_SIG, > 8*sizeof(uint8_t)); > +is_rsdp = acpi_check_signature(rsdp->v1.signature, ACPI_RSDP_SIG, > 8*sizeof(uint8_t)); > > if (is_rsdp != ACPI_SUCCESS) > return ACPI_BAD_SIGNATURE; > > -/* If match, calculates rdsp checksum and check It. */ > -checksum = acpi_checksum(rsdp, sizeof(struct acpi_rsdp)); > - > -if (checksum != 0) > -return ACPI_BAD_CHECKSUM; Don't we want to still check the checksum? (possibly fix it for the acpi 2.0 case) > +if (rsdp->v1.revision == 0) { > +// ACPI 1.0 > +*sdt_base = rsdp->v1.rsdt_addr; > +printf("ACPI v1.0\n"); > +return 1; > +} else if (rsdp->v1.revision == 2) { > +// ACPI >= 2.0 > +*sdt_base = rsdp->xsdt_addr; > +printf("ACPI >= v2.0\n"); > +return 2; > +} > > -return ACPI_SUCCESS; > +return ACPI_NO_RSDP; > } > > /* > @@ -147,38 +152,43 @@ acpi_check_rsdp_align(void *addr) > * > * Preconditions: The start address (addr) must be aligned. > * > - * Returns the reference to rsdp structure if success, NULL if failure. > + * Returns the physical address of rsdp structure if success, 0 if failure. > */ > -static struct acpi_rsdp* > -acpi_search_rsdp(void *addr, uint32_t length) > +static phys_addr_t > +acpi_search_rsdp(void *addr, uint32_t length, int *is_64bit) > { > void *end; > +int version = 0; There is no need to initialize version. > +phys_addr_t sdt_base = 0; > > /* Search RDSP in memory space between addr and addr+lenght. */ > for (end = addr+length; addr < end; addr += ACPI_RSDP_ALIGN) { > > /* Check if the current memory block stores the RDSP. */ > -if ((addr != NULL) && (acpi_check_rsdp(addr) == ACPI_SUCCESS)) { > -/* If yes, return RSDP address */ > -return (struct acpi_rsdp*) addr; > +if ((addr != NULL) && ((version = acpi_check_rsdp(addr, _base)) > > 0)) { > +/* If yes, return RSDT/XSDT address */ > +*is_64bit = 0; > +if (version == 2) > +*is_64bit = 1; You can make this *is_64bit = version == 2; > @@ -449,16 +527,9 @@ acpi_apic_parse_table(struct acpi_apic *apic) > static int > acpi_apic_setup(struct acpi_apic *apic) > { > -int apic_checksum; > ApicLocalUnit* lapic_unit; > uint8_t ncpus, nioapics; > > -/* Check the checksum of the APIC */ > -apic_checksum = acpi_checksum(apic, apic->header.length); > - > -if(apic_checksum != 0) > -return ACPI_BAD_CHECKSUM; Here as well we'd rather keep checking the checksum? Samuel
[PATCH 2/2 gnumach] ACPI: Support XSDT (ACPI >= v2.0)
--- i386/i386at/acpi_parse_apic.c | 203 -- i386/i386at/acpi_parse_apic.h | 18 ++- i386/i386at/model_dep.c | 8 +- 3 files changed, 169 insertions(+), 60 deletions(-) diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c index 9cd861ed..7b377d33 100644 --- a/i386/i386at/acpi_parse_apic.c +++ b/i386/i386at/acpi_parse_apic.c @@ -43,13 +43,12 @@ unsigned lapic_addr; * and the number of entries stored in RSDT. */ void -acpi_print_info(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, int acpi_rsdt_n) +acpi_print_info(phys_addr_t rsdp, void *rsdt, int acpi_rsdt_n) { printf("ACPI:\n"); -printf(" rsdp = %p; rsdp->rsdt_addr = %x\n", rsdp, rsdp->rsdt_addr); -printf(" rsdt = %p; rsdt->length = %x (n = %x)\n", rsdt, rsdt->header.length, - acpi_rsdt_n); +printf(" rsdp = 0x%lx\n", rsdp); +printf(" rsdt/xsdt = 0x%p (n = %d)\n", rsdt, acpi_rsdt_n); } /* @@ -99,27 +98,33 @@ acpi_check_signature(const uint8_t table_signature[], const char *real_signature * * Preconditions: RSDP pointer must not be NULL. * - * Returns 0 if correct. + * Returns 1 if ACPI 1.0 and sets sdt_base + * Returns 2 if ACPI >= 2.0 and sets sdt_base */ static int8_t -acpi_check_rsdp(struct acpi_rsdp *rsdp) +acpi_check_rsdp(struct acpi_rsdp2 *rsdp, phys_addr_t *sdt_base) { -uint32_t checksum; int is_rsdp; /* Check if rsdp signature match with the ACPI RSDP signature. */ -is_rsdp = acpi_check_signature(rsdp->signature, ACPI_RSDP_SIG, 8*sizeof(uint8_t)); +is_rsdp = acpi_check_signature(rsdp->v1.signature, ACPI_RSDP_SIG, 8*sizeof(uint8_t)); if (is_rsdp != ACPI_SUCCESS) return ACPI_BAD_SIGNATURE; -/* If match, calculates rdsp checksum and check It. */ -checksum = acpi_checksum(rsdp, sizeof(struct acpi_rsdp)); - -if (checksum != 0) -return ACPI_BAD_CHECKSUM; +if (rsdp->v1.revision == 0) { +// ACPI 1.0 +*sdt_base = rsdp->v1.rsdt_addr; +printf("ACPI v1.0\n"); +return 1; +} else if (rsdp->v1.revision == 2) { +// ACPI >= 2.0 +*sdt_base = rsdp->xsdt_addr; +printf("ACPI >= v2.0\n"); +return 2; +} -return ACPI_SUCCESS; +return ACPI_NO_RSDP; } /* @@ -147,38 +152,43 @@ acpi_check_rsdp_align(void *addr) * * Preconditions: The start address (addr) must be aligned. * - * Returns the reference to rsdp structure if success, NULL if failure. + * Returns the physical address of rsdp structure if success, 0 if failure. */ -static struct acpi_rsdp* -acpi_search_rsdp(void *addr, uint32_t length) +static phys_addr_t +acpi_search_rsdp(void *addr, uint32_t length, int *is_64bit) { void *end; +int version = 0; +phys_addr_t sdt_base = 0; /* Search RDSP in memory space between addr and addr+lenght. */ for (end = addr+length; addr < end; addr += ACPI_RSDP_ALIGN) { /* Check if the current memory block stores the RDSP. */ -if ((addr != NULL) && (acpi_check_rsdp(addr) == ACPI_SUCCESS)) { -/* If yes, return RSDP address */ -return (struct acpi_rsdp*) addr; +if ((addr != NULL) && ((version = acpi_check_rsdp(addr, _base)) > 0)) { +/* If yes, return RSDT/XSDT address */ +*is_64bit = 0; +if (version == 2) +*is_64bit = 1; +return sdt_base; } } -return NULL; +return 0; } /* * acpi_get_rsdp: tries to find the RSDP table, * searching It in many memory ranges, as It's written in ACPI Specification. * - * Returns the reference to RDSP structure if success, NULL if failure. + * Returns the reference to RDSP structure if success, 0 if failure. */ -static struct acpi_rsdp* -acpi_get_rsdp(void) +static phys_addr_t +acpi_get_rsdp(int *is_64bit) { uint16_t *start = 0; phys_addr_t base = 0; -struct acpi_rsdp *rsdp = NULL; +phys_addr_t rsdp = 0; /* EDBA start address. */ start = (uint16_t*) phystokv(0x040e); @@ -186,12 +196,12 @@ acpi_get_rsdp(void) /* check alignment. */ if (acpi_check_rsdp_align((void *)base) == ACPI_BAD_ALIGN) -return NULL; -rsdp = acpi_search_rsdp((void *)base, 1024); +return 0; +rsdp = acpi_search_rsdp((void *)base, 1024, is_64bit); -if (rsdp == NULL) { +if (rsdp == 0) { /* If RSDP isn't in EDBA, search in the BIOS read-only memory space between 0Eh and 0Fh */ -rsdp = acpi_search_rsdp((void *)phystokv(0xe), 0x10 - 0x0e); +rsdp = acpi_search_rsdp((void *)phystokv(0xe), 0x10 - 0x0e, is_64bit); } return rsdp; @@ -229,16 +239,13 @@ acpi_check_rsdt(struct acpi_rsdt *rsdt) * Returns the reference to RSDT table if success, NULL if error. */ static struct acpi_rsdt* -acpi_get_rsdt(struct acpi_rsdp *rsdp, int* acpi_rsdt_n) +acpi_get_rsdt(phys_addr_t rsdp_phys, int* acpi_rsdt_n) { -
Re: ACPI support
Hello, Damien Zammit, le sam. 25 avril 2020 09:38:31 +1000, a ecrit: > http://git.zammit.org/gnumach-sv.git/log/?h=debian-acpica > > It boots and prints a log but the problem I am facing is that > the log is not saved to /var/log/dmesg even though it prints at boot. > As it scrolls so fast, I cannot read it and I don't know how to have > it captured to the kernel log file. You can cat /dev/klog Samuel
ACPI support
Hi all, I have added ACPICA support to gnumach here: http://git.zammit.org/gnumach-sv.git/log/?h=debian-acpica It boots and prints a log but the problem I am facing is that the log is not saved to /var/log/dmesg even though it prints at boot. As it scrolls so fast, I cannot read it and I don't know how to have it captured to the kernel log file. Any thoughts? Thanks, Damien