From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93901+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93901+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299415; cv=none; d=zohomail.com; s=zohoarc; b=jTdWqcOXbtExPSxpo5VsDLiPPF/pOxLrAO9Pc9RuXqbXc/Rz8Awbpby2UTSwT1Yss+d9/rTLavGTIvfobvLSxJzS7mjL0Z3evMHXGPLbi8uTw9j0rpyEm71seQjiULKSMqG/qC0nbcmsnjuvDE13z1StRySPng1bJKf1NpqCqLA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299415; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=t4Hl4Onx1WD9CyGkDukBzFdfvuZOlb9IlMMoPQrshWg=; b=RpPB9MywUzkWjaIICZGEGLIGFioWcBf4etqUtey2bLL6To1+f1nAqe9cuXmrxspg3kQXBCvnrt6S58zp/P8LRz/7FfaJSmUwzzpWDKQRlrY0aZ06tspfvcxZnoWdsv6wZx8Y3STmekG11z7UcWPpgz4NspNZwV/vYJn6QYgEE6Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93901+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299415799785.727842268188; Thu, 15 Sep 2022 20:36:55 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 77OxYY1788612xy3IXAxskoE; Thu, 15 Sep 2022 20:36:55 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web11.2177.1663299405908021560 for ; Thu, 15 Sep 2022 20:36:54 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S3; Fri, 16 Sep 2022 11:36:35 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 01/16] Platform/Loongson: Add Serial Port library Date: Fri, 16 Sep 2022 11:36:18 +0800 Message-Id: <095000f9d109e3bd9c93b6c70e85626996a46754.1663298005.git.lixianglai@loongson.cn> In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S3 X-Coremail-Antispam: 1UD129KBjvAXoWfWFWxtF4xJr4ruF1fXFW7XFb_yoW5Aw4fXo WUZa1fAw1UJr1xuws5Gw17W3y8Aw4xZw1rJF4Fqa48W3Z3X3Z8uwn8Za95WwnxXryYgrn8 Gr1xtas5Ja9Iyryrn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: 1sQZ77Pmy9MSwIKOYL3Oqy4Vx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299415; bh=bjcTc/AH4PXTBjEf0LqGgBvZphQfQofOteiQYbsVVxA=; h=Cc:Date:From:Reply-To:Subject:To; b=Q58sTeHzGrWGuoJDGr0MHgjL5XR4jCBaRMKYvCpqiDfwLu5g5xsxy4D7uYqWDmFG2lg DAb3GISNDov3SHXYr76+E/o0DUyOb6XAtpaAok30CNE0+5yD8mswigYxsv9M5pOQv9Zla mX/xrAO7xgX6g2BVXHATNQJwf79RdWRFUXA= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299416333100054 Content-Type: text/plain; charset="utf-8" Serial Port library for LoongarchQemuPkg REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../LoongArchQemuPkg/Include/Library/Cpu.h | 387 +++++++++++ .../Include/LoongArchQemuPlatform.h | 97 +++ .../Library/SerialPortLib/SerialPortLib.c | 612 ++++++++++++++++++ .../Library/SerialPortLib/SerialPortLib.inf | 36 ++ 4 files changed, 1132 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQem= uPlatform.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLi= b/SerialPortLib.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLi= b/SerialPortLib.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h b/Pla= tform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h new file mode 100644 index 0000000000..8c3c21bd96 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/Cpu.h @@ -0,0 +1,387 @@ +/** @file + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - EXC - Exception + - INT - Interrupt + - FPU - Floating Point Unit + - CSR - CPU Status Register + - READQ - Read Quad Word +**/ +#ifndef LOONGARCH_CPU_H_ +#define LOONGARCH_CPU_H_ + +/* Exception types decoded by machdep exception decoder */ +#define EXC_INT 0 /* HW interrupt */ +#define EXC_TLBL 1 /* TLB miss on a load */ +#define EXC_TLBS 2 /* TLB miss on a store */ +#define EXC_TLBI 3 /* TLB miss on a ifetch */ +#define EXC_TLBM 4 /* TLB modified fault */ +#define EXC_TLBRI 5 /* TLB Read-Inhibit exception = */ +#define EXC_TLBXI 6 /* TLB Execution-Inhibit excep= tion */ +#define EXC_TLBPE 7 /* TLB Privilege Error */ +#define EXC_ADE 8 /* Address Error */ +#define EXC_ALE 9 /* Unalign Access */ +#define EXC_OOB 10 /* Out of bounds */ +#define EXC_SYS 11 /* System call */ +#define EXC_BP 12 /* Breakpoint */ +#define EXC_INE 13 /* Inst. Not Exist */ +#define EXC_IPE 14 /* Inst. Privileged Error */ +#define EXC_FPDIS 15 /* FPU Disabled */ +#define EXC_LSXDIS 16 /* LSX Disabled */ +#define EXC_LASXDIS 17 /* LASX Disabled */ +#define EXC_FPE 18 /* Floating Point Exception */ +#define EXC_WATCH 19 /* Watch address reference */ +#define EXC_BAD 255 /* Undecodeable */ + +#define COPY_SIGCODE // copy sigcode above user stack in exec +#define ZERO $r0 /* wired zero */ +#define RA $r1 /* return address */ +#define GP $r2 /* global pointer - caller saved f= or PIC */ +#define SP $r3 /* stack pointer */ +#define V0 $r4 /* return value - caller saved */ +#define V1 $r5 +#define A0 $r4 /* argument registers */ +#define A1 $r5 +#define A2 $r6 +#define A3 $r7 +#define A4 $r8 /* arg reg 64 bit; caller saved in= 32 bit */ +#define A5 $r9 +#define A6 $r10 +#define A7 $r11 +#define T0 $r12 /* caller saved */ +#define T1 $r13 +#define T2 $r14 +#define T3 $r15 +#define T4 $r16 /* callee saved */ +#define T5 $r17 +#define T6 $r18 +#define T7 $r19 +#define T8 $r20 /* caller saved */ +#define TP $r21 /* TLS */ +#define FP $r22 /* frame pointer */ +#define S0 $r23 /* callee saved */ +#define S1 $r24 +#define S2 $r25 +#define S3 $r26 +#define S4 $r27 +#define S5 $r28 +#define S6 $r29 +#define S7 $r30 +#define S8 $r31 /* callee saved */ + +#define FCSR0 $r0 + +// +// Location of the saved registers relative to ZERO. +// Usage is p->p_regs[XX]. +// +#define RA_NUM 1 +#define GP_NUM 2 +#define SP_NUM 3 +#define A0_NUM 4 +#define A1_NUM 5 +#define A2_NUM 6 +#define A3_NUM 7 +#define A4_NUM 8 +#define A5_NUM 9 +#define A6_NUM 10 +#define A7_NUM 11 +#define T0_NUM 12 +#define T1_NUM 13 +#define T2_NUM 14 +#define T3_NUM 15 +#define T4_NUM 16 +#define T5_NUM 17 +#define T6_NUM 18 +#define T7_NUM 19 +#define T8_NUM 20 +#define TP_NUM 21 +#define FP_NUM 22 +#define S0_NUM 23 +#define S1_NUM 24 +#define S2_NUM 25 +#define S3_NUM 26 +#define S4_NUM 27 +#define S5_NUM 28 +#define S6_NUM 29 +#define S7_NUM 30 +#define S8_NUM 31 + +#define FP0_NUM 0 +#define FP1_NUM 1 +#define FP2_NUM 2 +#define FP3_NUM 3 +#define FP4_NUM 4 +#define FP5_NUM 5 +#define FP6_NUM 6 +#define FP7_NUM 7 +#define FP8_NUM 8 +#define FP9_NUM 9 +#define FP10_NUM 10 +#define FP11_NUM 11 +#define FP12_NUM 12 +#define FP13_NUM 13 +#define FP14_NUM 14 +#define FP15_NUM 15 +#define FP16_NUM 16 +#define FP17_NUM 17 +#define FP18_NUM 18 +#define FP19_NUM 19 +#define FP20_NUM 20 +#define FP21_NUM 21 +#define FP22_NUM 22 +#define FP23_NUM 23 +#define FP24_NUM 24 +#define FP25_NUM 25 +#define FP26_NUM 26 +#define FP27_NUM 27 +#define FP28_NUM 28 +#define FP29_NUM 29 +#define FP30_NUM 30 +#define FP31_NUM 31 +#define FCSR_NUM 32 +#define FCC_NUM 33 + +#ifdef __ASSEMBLY__ +#define _ULCAST_ +#define _U64CAST_ +#else +#define _ULCAST_ (unsigned long) +#define _U64CAST_ (u64) +#endif + +#define LOONGARCH_CSR_CRMD 0 +#define LOONGARCH_CSR_PRMD 1 +#define LOONGARCH_CSR_EUEN 2 +#define CSR_EUEN_LBTEN_SHIFT 3 +#define CSR_EUEN_LBTEN (_ULCAST_(0x1) << CSR_EUEN_LBTEN_SHIFT) +#define CSR_EUEN_LASXEN_SHIFT 2 +#define CSR_EUEN_LASXEN (_ULCAST_(0x1) << CSR_EUEN_LASXEN_SHIF= T) +#define CSR_EUEN_LSXEN_SHIFT 1 +#define CSR_EUEN_LSXEN (_ULCAST_(0x1) << CSR_EUEN_LSXEN_SHIFT) +#define CSR_EUEN_FPEN_SHIFT 0 +#define CSR_EUEN_FPEN (_ULCAST_(0x1) << CSR_EUEN_FPEN_SHIFT) +#define LOONGARCH_CSR_ECFG 4 + +/* Exception status */ +#define LOONGARCH_CSR_ESTAT 5 +#define CSR_ESTAT_ESUBCODE_SHIFT 22 +#define CSR_ESTAT_ESUBCODE_WIDTH 9 +#define CSR_ESTAT_ESUBCODE (_ULCAST_(0x1ff) << CSR_ESTAT_ESUBCODE= _SHIFT) +#define CSR_ESTAT_EXC_SHIFT 16 +#define CSR_ESTAT_EXC_WIDTH 6 +#define CSR_ESTAT_EXC (_ULCAST_(0x3f) << CSR_ESTAT_EXC_SHIFT) +#define CSR_ESTAT_IS_SHIFT 0 +#define CSR_ESTAT_IS_WIDTH 15 +#define CSR_ESTAT_IS (_ULCAST_(0x7fff) << CSR_ESTAT_IS_SHIF= T) + +#define LOONGARCH_CSR_EPC 6 +#define LOONGARCH_CSR_BADV 7 +#define LOONGARCH_CSR_BADINST 8 +#define LOONGARCH_CSR_BADI 8 +#define LOONGARCH_CSR_EBASE 0xc /* Exception entry base addres= s */ +#define LOONGARCH_CSR_CPUNUM 0x20 /* CPU core number */ + +/* register number save in stack on exception */ +#define FP_BASE_NUM 34 +#define BASE_NUM 32 +#define CSR_NUM 10 +#define FP_BASE_INDEX (CSR_NUM + BASE_NUM) +#define BOOTCORE_ID 0 + +#define LOONGSON_IOCSR_IPI_STATUS 0x1000 +#define LOONGSON_IOCSR_IPI_EN 0x1004 +#define LOONGSON_IOCSR_IPI_SET 0x1008 +#define LOONGSON_IOCSR_IPI_CLEAR 0x100c +#define LOONGSON_CSR_MAIL_BUF0 0x1020 +#define LOONGSON_CSR_MAIL_BUF1 0x1028 +#define LOONGSON_CSR_MAIL_BUF2 0x1030 +#define LOONGSON_CSR_MAIL_BUF3 0x1038 + +/* Bit Domains for CFG registers */ +#define LOONGARCH_CPUCFG4 0x4 +#define LOONGARCH_CPUCFG5 0x5 + +/* Kscratch registers */ +#define LOONGARCH_CSR_KS0 0x30 +#define LOONGARCH_CSR_KS1 0x31 + +/* Stable timer registers */ +#define LOONGARCH_CSR_TMCFG 0x41 +#define LOONGARCH_CSR_TMCFG_EN (1ULL << 0) +#define LOONGARCH_CSR_TMCFG_PERIOD (1ULL << 1) +#define LOONGARCH_CSR_TMCFG_TIMEVAL (0x3fffffffffffULL << 2) +#define LOONGARCH_CSR_TVAL 0x42 /* Timer value */ +#define LOONGARCH_CSR_CNTC 0x43 /* Timer offset */ +#define LOONGARCH_CSR_TINTCLR 0x44 /* Timer interrupt clear */ + +/* TLB refill exception base address */ +#define LOONGARCH_CSR_TLBREBASE 0x88 +#define LOONGARCH_CSR_TLBRSAVE 0x8b /* KScratch for TLB refill ex= ception */ +#define LOONGARCH_CSR_PGD 0x1b /* Page table base */ + +/* Bits 8 and 9 of FPU Status Register specify the rounding mode */ +#define FPU_CSR_RM 0x300 +#define FPU_CSR_RN 0x000 /* nearest */ +#define FPU_CSR_RZ 0x100 /* towards zero */ +#define FPU_CSR_RU 0x200 /* towards +Infinity */ +#define FPU_CSR_RD 0x300 /* towards -Infinity */ + +/* + Reads data from the specified CSR register. + + @param[OUT] val The value is read from the CSR specified register. + @param[IN] reg Specifies the register number of the CSR to read the = data. + + @retval VOID + */ +#ifdef __GNUC__ +#define LOONGARCH_CSR_READQ(val, reg) \ +do { \ + UINT64 __res; \ + /* csrrd rd, csr_num */ \ + __asm__ __volatile__( \ + "csrrd %0, %1 \n\t" \ + :"=3Dr"(__res) \ + :"i"(reg) \ + : \ + ); \ + (val) =3D __res; \ +} while(0) +#endif + +/* + Write data to the specified CSR register. + + @param[OUT] val The value is write to the CSR specified register. + @param[IN] reg Specifies the register number of the CSR to write the= data. + + @retval VOID + */ +#ifdef __GNUC__ +#define LOONGARCH_CSR_WRITEQ(val, reg) \ +do { \ + UINT64 __val =3D val; \ + /* csrwr rd, csr_num */ \ + __asm__ __volatile__( \ + "csrwr %0, %1 \n\t" \ + : "+r"(__val) \ + : "i"(reg), "r"(__val) \ + : "memory" \ + ); \ +} while(0) +#endif + +/* + Exchange specified bit data with the specified CSR registers + + @param[IN] val The value Exchanged with the CSR specified register. + @param[IN] mask Specifies the mask for swapping bits + @param[IN] reg Specifies the register number of the CSR to Exchange = the data. + + @retval VOID + */ +#ifdef __GNUC__ +#define LOONGARCH_CSR_XCHGQ(val, mask, reg) \ +do { \ + UINT64 __val =3D val; \ + UINT64 __mask =3D mask; \ + /* csrwr rd, csr_num */ \ + __asm__ __volatile__( \ + "csrxchg %0, %1, %2 \n\t" \ + : "+r"(__val) \ + : "r"(__mask), "i"(reg), "r"(__val) \ + : "memory" \ + ); \ +} while(0) +#endif + +/* + Search for tlb + + @param VOID + + @retval VOID + */ +#ifdef __GNUC__ +#define LOONGARCH_TLB_SRCH() \ +do { \ + /* tlbsrch */ \ + __asm__ __volatile__( \ + "tlbsrch" \ + ); \ +} while(0) +#endif + +/* + Writes data to the specified tlb table entry. + + @param VOID + + @retval VOID + */ +#ifdef __GNUC__ +#define LOONGARCH_TLB_WR() \ +do { \ + /* tlbwr */ \ + __asm__ __volatile__( \ + "tlbwr" \ + ); \ +} while(0) +#endif +/* + Reads data from the specified CPUCFG register. + + @param[OUT] val The value is read from the CPUCFG specified register. + @param[IN] reg Specifies the register number of the CPUCFG to read t= he data. + + @retval VOID + */ +#ifdef __GNUC__ +#define LOONGARCH_GET_CPUCFG(val, reg) \ +do { \ + UINT64 __res; \ + /* cpucfg rd, rj */ \ + __asm__ __volatile__( \ + "cpucfg %0, %1 \n\t" \ + :"=3Dr"(__res) \ + :"r"(reg) \ + : \ + ); \ + val =3D (UINT32)__res; \ +} while(0) +#endif + +/* + Enables floating-point unit + + @param VOID + + @retval VOID + */ +#define LOONGARCH_ENABLR_FPU() \ +do { \ + LOONGARCH_CSR_XCHGQ(CSR_EUEN_FPEN, \ + CSR_EUEN_FPEN, \ + LOONGARCH_CSR_EUEN); \ +} while (0) + +/* + Disable floating-point unit + + @param VOID + + @retval VOID + */ +#define LOONGARCH_DISABLE_FPU() \ +do { \ + LOONGARCH_CSR_XCHGQ(0, \ + CSR_EUEN_FPEN, \ + LOONGARCH_CSR_EUEN); \ +} while (0) + +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatfo= rm.h b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h new file mode 100644 index 0000000000..ed672844b4 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h @@ -0,0 +1,97 @@ +/** @file + LoongArch Qemu Platform macro definition. + + Copyright (c) 2021, Loongson Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ + +#ifndef LOONGARCH_QEMU_PLATFORM_H_ +#define LOONGARCH_QEMU_PLATFORM_H_ + + +/* Acpi pm device */ +#define LS7A_PCH_REG_BASE 0x10000000UL +#define LS7A_ACPI_REG_BASE (LS7A_PCH_REG_BASE + 0x000D0000) +#define LS7A_PM_CNT_BLK (0x14) /* 2 bytes */ +#define LS7A_GPE0_RESET_REG (0x30) /* 4 bytes */ + +#define ACPI_BITMASK_SLEEP_TYPE 0x1C00 +#define ACPI_BITMASK_SLEEP_ENABLE 0x2000 + + +//--------------------------------------------- +// UART Register Offsets +//--------------------------------------------- +#define BAUD_LOW_OFFSET 0x00 +#define BAUD_HIGH_OFFSET 0x01 +#define IER_OFFSET 0x01 +#define LCR_SHADOW_OFFSET 0x01 +#define FCR_SHADOW_OFFSET 0x02 +#define IR_CONTROL_OFFSET 0x02 +#define FCR_OFFSET 0x02 +#define EIR_OFFSET 0x02 +#define BSR_OFFSET 0x03 +#define LCR_OFFSET 0x03 +#define MCR_OFFSET 0x04 +#define LSR_OFFSET 0x05 +#define MSR_OFFSET 0x06 + +/* character format control register */ +#define CFCR_DLAB 0x80 /* divisor latch */ +#define CFCR_SBREAK 0x40 /* send break */ +#define CFCR_PZERO 0x30 /* zero parity */ +#define CFCR_PONE 0x20 /* one parity */ +#define CFCR_PEVEN 0x10 /* even parity */ +#define CFCR_PODD 0x00 /* odd parity */ +#define CFCR_PENAB 0x08 /* parity enable */ +#define CFCR_STOPB 0x04 /* 2 stop bits */ +#define CFCR_8BITS 0x03 /* 8 data bits */ +#define CFCR_7BITS 0x02 /* 7 data bits */ +#define CFCR_6BITS 0x01 /* 6 data bits */ +#define CFCR_5BITS 0x00 /* 5 data bits */ +/* modem control register */ +#define MCR_LOOPBACK 0x10 /* loopback */ +#define MCR_IENABLE 0x08 /* output 2 =3D int enable */ +#define MCR_DRS 0x04 /* output 1 =3D xxx */ +#define MCR_RTS 0x02 /* enable RTS */ +#define MCR_DTR 0x01 /* enable DTR */ + +/* line status register */ +#define LSR_RCV_FIFO 0x80 /* error in receive fifo */ +#define LSR_TSRE 0x40 /* transmitter empty */ +#define LSR_TXRDY 0x20 /* transmitter ready */ +#define LSR_BI 0x10 /* break detected */ +#define LSR_FE 0x08 /* framing error */ +#define LSR_PE 0x04 /* parity error */ +#define LSR_OE 0x02 /* overrun error */ +#define LSR_RXRDY 0x01 /* receiver ready */ +#define LSR_RCV_MASK 0x1f + +/* 16550 UART register offsets and bitfields */ +#define R_UART_RXBUF 0 +#define R_UART_TXBUF 0 +#define R_UART_BAUD_LOW 0 +#define R_UART_BAUD_HIGH 1 +#define R_UART_FCR 2 +#define B_UART_FCR_FIFOE BIT0 +#define B_UART_FCR_FIFO64 BIT5 +#define R_UART_LCR 3 +#define B_UART_LCR_DLAB BIT7 +#define R_UART_MCR 4 +#define B_UART_MCR_DTRC BIT0 +#define B_UART_MCR_RTS BIT1 +#define R_UART_LSR 5 +#define B_UART_LSR_RXRDY BIT0 +#define B_UART_LSR_TXRDY BIT5 +#define B_UART_LSR_TEMT BIT6 +#define R_UART_MSR 6 +#define B_UART_MSR_CTS BIT4 +#define B_UART_MSR_DSR BIT5 +#define B_UART_MSR_RI BIT6 +#define B_UART_MSR_DCD BIT7 +#define UART_BASE_ADDRESS (0x1fe001e0) +#define UART_BPS (115200) +#define UART_WAIT_TIMOUT (1000000) +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/Seria= lPortLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/Seria= lPortLib.c new file mode 100644 index 0000000000..eb1ce17d69 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLi= b.c @@ -0,0 +1,612 @@ +/** @file + UART Serial Port library functions + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Bps - Bit Per Second + - CTL - Control + - Config - Configure +**/ + +#include +#include +#include +#include +#include + +UINTN gUartBase =3D UART_BASE_ADDRESS; +UINTN gBps =3D UART_BPS; + +/** + Initialize the serial device hardware. + + If no initialization is required, then return RETURN_SUCCESS. + If the serial device was successfuly initialized, then return RETURN_SUC= CESS. + If the serial device could not be initialized, then return RETURN_DEVICE= _ERROR. + + @retval RETURN_SUCCESS The serial device was initialized. + @retval RETURN_DEVICE_ERROR The serail device could not be initialized. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + UINTN TimeOut; + // + // wait for Tx fifo to completely drain */ + // + TimeOut =3D UART_WAIT_TIMOUT; + while (!(MmioRead8 ((UINTN) gUartBase + LSR_OFFSET) & LSR_TSRE)) { + if (--TimeOut =3D=3D 0) { + break; + } + } + // + // Set communications format + // + MmioWrite8 ((UINTN) (gUartBase + LCR_OFFSET), CFCR_DLAB); + + // + // Configure baud rate + // + + + MmioWrite8 ((UINTN) (gUartBase + LCR_OFFSET), CFCR_8BITS); + MmioWrite8 ((UINTN) (gUartBase + MCR_OFFSET), MCR_IENABLE | MCR_DTR | MC= R_RTS); + // + // if enable interrupt the kernel of lemote will error in STR mode durin= g wake up phase. + // + //MmioWrite8 ((UINTN) (gUartBase + IER_OFFSET), CFCR_8BITS); + + return RETURN_SUCCESS; +} + +/** + Write data from buffer to serial device. + + Writes NumberOfBytes data bytes from Buffer to the serial device. + The number of bytes actually written to the serial device is returned. + If the return value is less than NumberOfBytes, then the write operation= failed. + + If Buffer is NULL, then ASSERT (). + + If NumberOfBytes is zero, then return 0. + + @param Buffer Pointer to the data buffer to be written. + @param NumberOfBytes Number of bytes to written to the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes written to the serial devic= e. + If this value is less than NumberOfBytes, then = the read operation failed. + +**/ +UINTN +EFIAPI +UartCtlWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes, + IN UINTN CtlAddr +) +{ + UINTN Result; + UINT8 Data; + + if (Buffer =3D=3D NULL) { + return 0; + } + + Result =3D NumberOfBytes; + + while (NumberOfBytes--) { + // + // Wait for the serail port to be ready. + // + do { + Data =3D MmioRead8 (CtlAddr + LSR_OFFSET); + } while ((Data & LSR_TXRDY) =3D=3D 0); + MmioWrite8 (CtlAddr, *Buffer++); + } + + return Result; +} +/** + Writes data to serial port. + + @param Buffer Pointer to the data buffer to store the data wr= ited to serial port. + @param NumberOfBytes Number of bytes to write to the serial port. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes write the serial port. + If this value is less than NumberOfBytes, then = the write operation failed. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + return UartCtlWrite (Buffer, NumberOfBytes, gUartBase); +} +/** + Reads data from a serial device into a buffer. + + @param Buffer Pointer to the data buffer to store the data re= ad from the serial device. + @param NumberOfBytes Number of bytes to read from the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes read from the serial device. + If this value is less than NumberOfBytes, then = the read operation failed. + +**/ +UINTN +EFIAPI +UartCtlRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes, + IN UINTN CtlAddr +) +{ + UINTN Result; + UINT8 Data; + + if (NULL =3D=3D Buffer) { + return 0; + } + + Result =3D NumberOfBytes; + + while (NumberOfBytes--) { + // + // Wait for the serail port to be ready. + // + do { + Data =3D MmioRead8 (CtlAddr + LSR_OFFSET); + } while ((Data & LSR_RXRDY) =3D=3D 0); + + *Buffer++ =3D MmioRead8 (CtlAddr); + } + + return Result; +} +/** + Read data from serial port. + + @param Buffer Pointer to the data buffer to store the data re= ad from serial port. + @param NumberOfBytes Number of bytes to read from the serial port. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes read from the serial port. + If this value is less than NumberOfBytes, then = the read operation failed. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + return UartCtlRead (Buffer, NumberOfBytes, gUartBase); +} +/** + Polls a serial device to see if there is any data waiting to be read. + + Polls aserial device to see if there is any data waiting to be read. + If there is data waiting to be read from the serial device, then TRUE is= returned. + If there is no data waiting to be read from the serial device, then FALS= E is returned. + + @retval TRUE Data is waiting to be read from the serial devi= ce. + @retval FALSE There is no data waiting to be read from the se= rial device. + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + UINT8 Data; + + // + // Read the serial port status. + // + Data =3D MmioRead8 ((UINTN) gUartBase + LSR_OFFSET); + + return (BOOLEAN) ((Data & LSR_RXRDY) !=3D 0); +} +/** + To get serial register base address. + + @param VOID + + @return serial register base address. +**/ +UINTN +GetSerialRegisterBase ( + VOID + ) +{ + return gUartBase; +} +/** + Read an 8-bit register. + @param Base The base address register of UART device. + @param Offset The offset of the register to read. + + @return The value read from the 16550 register. + +**/ +UINT8 +SerialPortReadRegister ( + UINTN Base, + UINTN Offset + ) +{ + return MmioRead8 (Base + Offset); +} + +/** + Write an 8-bit register. + @param Base The base address register of UART device. + @param Offset The offset of the register to write. + @param Value The value to write to the register specified by Offset. + + @return The value written to the 16550 register. + +**/ +UINT8 +SerialPortWriteRegister ( + UINTN Base, + UINTN Offset, + UINT8 Value + ) +{ + return MmioWrite8 (Base + Offset, Value); +} + +/** + Sets the control bits on a serial device. + + @param Control Sets the bits of Control that are settable. + + @retval RETURN_SUCCESS The new control bits were set on the seria= l device. + @retval RETURN_UNSUPPORTED The serial device does not support this op= eration. + @retval RETURN_DEVICE_ERROR The serial device is not functioning corre= ctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + UINTN SerialRegisterBase; + UINT8 Mcr; + + // + // First determine the parameter is invalid. + // + if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_= READY | + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) !=3D 0) + { + return RETURN_UNSUPPORTED; + } + + SerialRegisterBase =3D GetSerialRegisterBase (); + if (SerialRegisterBase =3D=3D0) { + return RETURN_UNSUPPORTED; + } + + // + // Read the Modem Control Register. + // + Mcr =3D SerialPortReadRegister (SerialRegisterBase, R_UART_MCR); + Mcr &=3D (~(B_UART_MCR_DTRC | B_UART_MCR_RTS)); + + if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) =3D=3D EFI_SERIAL_DATA_TE= RMINAL_READY) { + Mcr |=3D B_UART_MCR_DTRC; + } + + if ((Control & EFI_SERIAL_REQUEST_TO_SEND) =3D=3D EFI_SERIAL_REQUEST_TO_= SEND) { + Mcr |=3D B_UART_MCR_RTS; + } + + // + // Write the Modem Control Register. + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr); + + return RETURN_SUCCESS; +} + +/** + Retrieve the status of the control bits on a serial device. + + @param Control A pointer to return the current control si= gnals from the serial device. + + @retval RETURN_SUCCESS The control bits were read from the serial= device. + @retval RETURN_UNSUPPORTED The serial device does not support this op= eration. + @retval RETURN_DEVICE_ERROR The serial device is not functioning corre= ctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + UINTN SerialRegisterBase; + UINT8 Msr; + UINT8 Mcr; + UINT8 Lsr; + + SerialRegisterBase =3D GetSerialRegisterBase (); + if (SerialRegisterBase =3D=3D0) { + return RETURN_UNSUPPORTED; + } + + *Control =3D 0; + + // + // Read the Modem Status Register. + // + Msr =3D SerialPortReadRegister (SerialRegisterBase, R_UART_MSR); + + if ((Msr & B_UART_MSR_CTS) =3D=3D B_UART_MSR_CTS) { + *Control |=3D EFI_SERIAL_CLEAR_TO_SEND; + } + + if ((Msr & B_UART_MSR_DSR) =3D=3D B_UART_MSR_DSR) { + *Control |=3D EFI_SERIAL_DATA_SET_READY; + } + + if ((Msr & B_UART_MSR_RI) =3D=3D B_UART_MSR_RI) { + *Control |=3D EFI_SERIAL_RING_INDICATE; + } + + if ((Msr & B_UART_MSR_DCD) =3D=3D B_UART_MSR_DCD) { + *Control |=3D EFI_SERIAL_CARRIER_DETECT; + } + + // + // Read the Modem Control Register. + // + Mcr =3D SerialPortReadRegister (SerialRegisterBase, R_UART_MCR); + + if ((Mcr & B_UART_MCR_DTRC) =3D=3D B_UART_MCR_DTRC) { + *Control |=3D EFI_SERIAL_DATA_TERMINAL_READY; + } + + if ((Mcr & B_UART_MCR_RTS) =3D=3D B_UART_MCR_RTS) { + *Control |=3D EFI_SERIAL_REQUEST_TO_SEND; + } + + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + *Control |=3D EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; + } + + // + // Read the Line Status Register. + // + Lsr =3D SerialPortReadRegister (SerialRegisterBase, R_UART_LSR); + + if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) =3D=3D (B_UART_LSR_TEMT= | B_UART_LSR_TXRDY)) { + *Control |=3D EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + + if ((Lsr & B_UART_LSR_RXRDY) =3D=3D 0) { + *Control |=3D EFI_SERIAL_INPUT_BUFFER_EMPTY; + } + + return RETURN_SUCCESS; +} + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parit= y, + data bits, and stop bits on a serial device. + + @param BaudRate The requested baud rate. A BaudRate value of 0= will use the + device's default interface speed. + On output, the value actually set. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive= side of the + serial interface. A ReceiveFifoDepth value of = 0 will use + the device's default FIFO depth. + On output, the value actually set. + @param Timeout The requested time out for a single character = in microseconds. + This timeout applies to both the transmit and = receive side of the + interface. A Timeout value of 0 will use the d= evice's default time + out value. + On output, the value actually set. + @param Parity The type of parity to use on this serial devic= e. A Parity value of + DefaultParity will use the device's default pa= rity value. + On output, the value actually set. + @param DataBits The number of data bits to use on the serial d= evice. A DataBits + vaule of 0 will use the device's default data = bit setting. + On output, the value actually set. + @param StopBits The number of stop bits to use on this serial = device. A StopBits + value of DefaultStopBits will use the device's= default number of + stop bits. + On output, the value actually set. + + @retval RETURN_SUCCESS The new attributes were set on the ser= ial device. + @retval RETURN_UNSUPPORTED The serial device does not support thi= s operation. + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an u= nsupported value. + @retval RETURN_DEVICE_ERROR The serial device is not functioning c= orrectly. + +**/ +RETURN_STATUS +EFIAPI +UartCtlConfig ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits, + IN UINTN CtlAddr + ) +{ + UINTN SerialRegisterBase; + UINT8 Lcr; + UINT8 LcrData; + UINT8 LcrParity; + UINT8 LcrStop; + + + SerialRegisterBase =3D CtlAddr; + if (SerialRegisterBase =3D=3D0) { + return RETURN_UNSUPPORTED; + } + + // + // Check for default settings and fill in actual values. + // + if (*BaudRate =3D=3D 0) { + *BaudRate =3D PcdGet32 (PcdSerialBaudRate); + } + + if (*DataBits =3D=3D 0) { + LcrData =3D (UINT8) (PcdGet8 (PcdSerialLineControl) & 0x3); + *DataBits =3D LcrData + 5; + } else { + if ((*DataBits < 5) + || (*DataBits > 8)) + { + return RETURN_INVALID_PARAMETER; + } + // + // Map 5..8 to 0..3 + // + LcrData =3D (UINT8) (*DataBits - (UINT8) 5); + } + + if (*Parity =3D=3D DefaultParity) { + LcrParity =3D (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7); + switch (LcrParity) { + case 0: + *Parity =3D NoParity; + break; + + case 3: + *Parity =3D EvenParity; + break; + + case 1: + *Parity =3D OddParity; + break; + + case 7: + *Parity =3D SpaceParity; + break; + + case 5: + *Parity =3D MarkParity; + break; + + default: + break; + } + } else { + switch (*Parity) { + case NoParity: + LcrParity =3D 0; + break; + + case EvenParity: + LcrParity =3D 3; + break; + + case OddParity: + LcrParity =3D 1; + break; + + case SpaceParity: + LcrParity =3D 7; + break; + + case MarkParity: + LcrParity =3D 5; + break; + + default: + return RETURN_INVALID_PARAMETER; + } + } + + if (*StopBits =3D=3D DefaultStopBits) { + LcrStop =3D (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1); + switch (LcrStop) { + case 0: + *StopBits =3D OneStopBit; + break; + + case 1: + if (*DataBits =3D=3D 5) { + *StopBits =3D OneFiveStopBits; + } else { + *StopBits =3D TwoStopBits; + } + break; + + default: + break; + } + } else { + switch (*StopBits) { + case OneStopBit: + LcrStop =3D 0; + break; + + case OneFiveStopBits: + case TwoStopBits: + LcrStop =3D 1; + break; + + default: + return RETURN_INVALID_PARAMETER; + } + } + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB= ); + + // + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. + // Strip reserved bits from line control value + // + Lcr =3D (UINT8) ((LcrParity << 3) | (LcrStop << 2) | LcrData); + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8) (Lcr & = 0x3F)); + + return RETURN_SUCCESS; +} +/** + Set the serial port Attributes. + + @param VOID + + @return serial register base address. +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits + ) +{ + UINTN SerialRegisterBase; + + SerialRegisterBase =3D GetSerialRegisterBase (); + + return UartCtlConfig (&gBps, ReceiveFifoDepth, Timeout, Parity, DataBit= s, StopBits, + SerialRegisterBase); +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/Seria= lPortLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/Ser= ialPortLib.inf new file mode 100644 index 0000000000..6c4674151b --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLi= b.inf @@ -0,0 +1,36 @@ +## @file +# UART Serial Port library functions +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PcAtSerialPortLib + FILE_GUID =3D f4fb883d-8138-4f29-bb0c-c574e9312c74 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D SerialPortLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + +[LibraryClasses] + BaseLib + IoLib + PcdLib + +[Sources] + SerialPortLib.c + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl ## CONSU= MES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate ## CONSU= MES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl ## CONSU= MES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate ## CONSU= MES --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93901): https://edk2.groups.io/g/devel/message/93901 Mute This Topic: https://groups.io/mt/93715820/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93892+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93892+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299405; cv=none; d=zohomail.com; s=zohoarc; b=EY0+SQSgUlEyHqL94ZbtpqEK7MyeCIzvtd0+byzzqYPgY8eWL7pSbU3jy6T0t+tlXR9nZsesTaPKpVO6KFtl79+O009Y1+kng/+3803EjLMnBEOiB6iyUrBsFk7Oah97I8BZ4nljTUTG0lWdKfVzxHLY755Hf8BHUBe8XeMMfcM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299405; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=OAroBBeYgTRyzOktFJydAmBNXvxC7njWbUHVasFJ1kQ=; b=nAj5Vhhdig5ndMfjr9UmGuMkk6bxy1OU7z6gRc34yUsu8TdouMP8p8ttcz0rXpC+5G1dCS7oVfxuXp93AJYeByf1GwIUkZKl5dS5A/TRNBqSIVU2Nh/NMpLI4HbqRK/8JktVK6AKxaV5NFyVjbNlRshmJ9Vpwrdw9fkX2rl51bI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93892+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299405558667.1708951894165; Thu, 15 Sep 2022 20:36:45 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id R592YY1788612xu538shUQfK; Thu, 15 Sep 2022 20:36:45 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web12.2041.1663299401037147215 for ; Thu, 15 Sep 2022 20:36:43 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S4; Fri, 16 Sep 2022 11:36:36 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 02/16] Platform/Loongson: Support SEC And Add Readme.md Date: Fri, 16 Sep 2022 11:36:19 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S4 X-Coremail-Antispam: 1UD129KBjvAXoWfAr47XrW3JFy7ZryUCw1fCrg_yoW5KFWkAo WxWFWIkw48Gr1rX3WUGFnrJrW8AF1Fqa15tr1FqayDGF4Yyrn8ta98J3s7Gw15Awn8J3Z8 G34rGaykJFW7ta4kn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: diEPibYvKXaeptpKVcx9Yny5x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299405; bh=yHmRIr4fMHjjQA/rzGQJH/sfN0s4xHbtvidmJ3/pkgQ=; h=Cc:Date:From:Reply-To:Subject:To; b=wD73E0Jxc1SdhKL8uNNAyfhbd6UMEpvuHCFhOPL3fuLBvoc0RR1V4CjbyV5xbnvtwjd x9yqY3IRDo89VM3lKTy5+xB/IJbxd2wciU3FD7YaQl4fpBEguIIJMivGxOJ596PfoGbsS UVogAvDk4m429BDlcduMTgfvi0PRG8WbnSY= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299406312100013 Content-Type: text/plain; charset="utf-8" Add SEC Code And Readme.md for LoongArchQemu REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li Signed-off-by: xianglai li --- Maintainers.txt | 4 + .../Include/LoongArchAsmMacro.h | 23 + .../Loongson/LoongArchQemuPkg/Loongson.dec | 38 ++ .../Loongson/LoongArchQemuPkg/Loongson.dsc | 133 +++++ .../Loongson/LoongArchQemuPkg/Loongson.fdf | 53 ++ .../LoongArchQemuPkg/Loongson.fdf.inc | 21 + Platform/Loongson/LoongArchQemuPkg/Readme.md | 59 ++ .../LoongArchQemuPkg/Sec/LoongArch64/Start.S | 76 +++ .../Loongson/LoongArchQemuPkg/Sec/SecMain.c | 510 ++++++++++++++++++ .../Loongson/LoongArchQemuPkg/Sec/SecMain.inf | 49 ++ Readme.md | 9 + 11 files changed, 975 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/LoongArchAsm= Macro.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Loongson.dec create mode 100644 Platform/Loongson/LoongArchQemuPkg/Loongson.dsc create mode 100644 Platform/Loongson/LoongArchQemuPkg/Loongson.fdf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc create mode 100644 Platform/Loongson/LoongArchQemuPkg/Readme.md create mode 100644 Platform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Star= t.S create mode 100644 Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf diff --git a/Maintainers.txt b/Maintainers.txt index 700ca0af60..8921d6b4e1 100644 --- a/Maintainers.txt +++ b/Maintainers.txt @@ -329,6 +329,10 @@ M: Bob Feng M: Liming Gao R: Yuwei Chen =20 +Loongson platforms +F: Platform/Loongson/ +M: xianglai li + Marvell platforms and silicon F: Platform/Marvell/ F: Platform/SolidRun/Armada80x0McBin/ diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchAsmMacro.h= b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchAsmMacro.h new file mode 100644 index 0000000000..366d4308e8 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchAsmMacro.h @@ -0,0 +1,23 @@ +/** @file + LoongArch ASM macro definition. + + Copyright (c) 2021, Loongson Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ + +#ifndef LOONGARCH_ASM_MACRO_H_ +#define LOONGARCH_ASM_MACRO_H_ + +#include + +#define _ASM_FUNC(Name, Section) \ + .global Name ; \ + .section #Section, "ax" ; \ + .type Name, %function ; \ + Name: + +#define ASM_FUNC(Name) _ASM_FUNC(ASM_PFX(Name), .text. ## Name) + +#endif // __LOONGARCH_ASM_MACRO_H__ diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.dec new file mode 100644 index 0000000000..248b668fd1 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec @@ -0,0 +1,38 @@ +## @file +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION =3D 0x00010005 + PACKAGE_NAME =3D LoongArchQemuPkg + PACKAGE_GUID =3D b51d765a-41da-45fc-a537-de3ee785c0f6 + PACKAGE_VERSION =3D 0.1 + +##########################################################################= ###### +# +# Include Section - list of Include Paths that are provided by this packag= e. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_D= RIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +##########################################################################= ###### +[Includes.common] + Include # Root include for the package + +[Guids] + gLoongArchQemuPkgTokenSpaceGuid =3D { 0x0e0383ce, 0x0151, 0x4d01, { 0x8= 0, 0x0e, 0x3f, 0xef, 0x8b, 0x27, 0x6d, 0x52 } } + +[PcdsFixedAtBuild, PcdsDynamic] + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase|0x0|UINT64|0x00000003 + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize|0x0|UINT32|0x00000004 + gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0|UINT3= 2|0x00000016 + gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|0|UI= NT32|0x00000017 + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase|0|UINT64|0x0000001c + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize|0|UINT32|0x0000001d + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase|0x0|UINT64|0x00000028 + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize|0x0|UINT32|0x00000029 diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.dsc new file mode 100644 index 0000000000..f23fed77e6 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc @@ -0,0 +1,133 @@ +## @file +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +##########################################################################= ###### +# +# Defines Section - statements that will be processed to create a Makefile. +# +##########################################################################= ##### +[Defines] + PLATFORM_NAME =3D LoongArchQemu + PLATFORMPKG_NAME =3D LoongArchQemu + PLATFORM_GUID =3D 7926ea52-b0dc-4ee8-ac63-341eebd84ed4 + PLATFORM_VERSION =3D 0.1 + DSC_SPECIFICATION =3D 0x00010005 + OUTPUT_DIRECTORY =3D Build/$(PLATFORM_NAME) + SUPPORTED_ARCHITECTURES =3D LOONGARCH64 + BUILD_TARGETS =3D DEBUG|RELEASE + SKUID_IDENTIFIER =3D DEFAULT + FLASH_DEFINITION =3D Platform/Loongson/LoongArchQemuPkg/Lo= ongson.fdf + TTY_TERMINAL =3D FALSE + +##########################################################################= ## +# +# Defines for default states. These can be changed on the command line. +# -D FLAG=3DVALUE +##########################################################################= ## +[BuildOptions] + GCC:RELEASE_*_*_CC_FLAGS =3D -DSPEEDUP + + # + # Disable deprecated APIs. + # + GCC:*_*_*_CC_FLAGS =3D -D DISABLE_NEW_DEPRECATED_INTERFACES + + +[BuildOptions.LOONGARCH64.EDKII.SEC] + *_*_*_CC_FLAGS =3D + +#[BuildOptions.common.EDKII.DXE_CORE,BuildOptions.common.EDKII.DXE_DRIVER,= BuildOptions.common.EDKII.UEFI_DRIVER,BuildOptions.common.EDKII.UEFI_APPLIC= ATION] +# GCC:*_*_*_DLINK_FLAGS =3D -z common-page-size=3D0x1000 + +[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER] + GCC:*_*_LOONGARCH64_DLINK_FLAGS =3D -z common-page-size=3D0x10000 + +##########################################################################= ###### +# +# Library Class section - list of all Library Classes needed by this Platf= orm. +# +##########################################################################= ###### + +!include MdePkg/MdeLibs.dsc.inc + +[LibraryClasses.common] + PcdLib | MdePkg/Library/BasePcdLibNull/BasePcd= LibNull.inf + PrintLib | MdePkg/Library/BasePrintLib/BasePrint= Lib.inf + BaseMemoryLib | MdePkg/Library/BaseMemoryLib/BaseMemo= ryLib.inf + + + BaseLib | MdePkg/Library/BaseLib/BaseLib.inf + PeCoffLib | MdePkg/Library/BasePeCoffLib/BasePeCo= ffLib.inf + PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPoin= tLib/BasePeCoffGetEntryPointLib.inf + IoLib | MdePkg/Library/BaseIoLibIntrinsic/Bas= eIoLibIntrinsic.inf + SerialPortLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/SerialPortLib/SerialPortLib.inf + DebugPrintErrorLevelLib | MdePkg/Library/BaseDebugPrintErrorLev= elLib/BaseDebugPrintErrorLevelLib.inf + PeCoffExtraActionLib | MdePkg/Library/BasePeCoffExtraActionL= ibNull/BasePeCoffExtraActionLibNull.inf + DebugAgentLib | MdeModulePkg/Library/DebugAgentLibNul= l/DebugAgentLibNull.inf + + DebugLib | MdePkg/Library/BaseDebugLibSerialPort= /BaseDebugLibSerialPort.inf + + + + +##########################################################################= ###### +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform. +# +##########################################################################= ###### +[PcdsFixedAtBuild] +## BaseLib ## + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength | 1= 000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength | 1= 000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength | 1= 000000 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel | 0= x8000004F + # DEBUG_INIT 0x00000001 // Initialization + # DEBUG_WARN 0x00000002 // Warnings + # DEBUG_LOAD 0x00000004 // Load events + # DEBUG_FS 0x00000008 // EFI File system + # DEBUG_POOL 0x00000010 // Alloc & Free (pool) + # DEBUG_PAGE 0x00000020 // Alloc & Free (page) + # DEBUG_INFO 0x00000040 // Informational debug messages + # DEBUG_DISPATCH 0x00000080 // PEI/DXE/SMM Dispatchers + # DEBUG_VARIABLE 0x00000100 // Variable + # DEBUG_BM 0x00000400 // Boot Manager + # DEBUG_BLKIO 0x00001000 // BlkIo Driver + # DEBUG_NET 0x00004000 // Network Io Driver + # DEBUG_UNDI 0x00010000 // UNDI Driver + # DEBUG_LOADFILE 0x00020000 // LoadFile + # DEBUG_EVENT 0x00080000 // Event messages + # DEBUG_GCD 0x00100000 // Global Coherency Database changes + # DEBUG_CACHE 0x00200000 // Memory range cachability changes + # DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may + # DEBUG_ERROR 0x80000000 // Error + +!if $(TARGET) =3D=3D RELEASE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask | 0= x21 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask | 0= x2f +!endif + # DEBUG_ASSERT_ENABLED 0x01 + # DEBUG_PRINT_ENABLED 0x02 + # DEBUG_CODE_ENABLED 0x04 + # CLEAR_MEMORY_ENABLED 0x08 + # ASSERT_BREAKPOINT_ENABLED 0x10 + # ASSERT_DEADLOOP_ENABLED 0x20 + + gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress | 0= x90000000 + gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize | 0= x10000 + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase | 0= x90010000 + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize | 0= x10000 + + +[Components] + + # + # SEC Phase modules + # + Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.fdf new file mode 100644 index 0000000000..128b3843db --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf @@ -0,0 +1,53 @@ +## @file +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +##########################################################################= ########################### +[Defines] +!include Loongson.fdf.inc + +##########################################################################= ########################### +[FD.QEMU_EFI] +BaseAddress =3D $(FD_BASE_ADDRESS) +Size =3D $(FD_SIZE) +ErasePolarity =3D 1 +BlockSize =3D $(BLOCK_SIZE) +NumBlocks =3D $(FD_BLOCKS) + +$(SECFV_OFFSET)|$(SECFV_SIZE) +gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase|gLoongArchQemuPkgTokenSp= aceGuid.PcdFlashSecFvSize +FV =3D SECFV + +##########################################################################= ########################### +[FV.SECFV] +FvNameGuid =3D 587d4265-5e71-41da-9c35-4258551f1e22 +BlockSize =3D $(BLOCK_SIZE) +FvAlignment =3D 16 +ERASE_POLARITY =3D 1 +MEMORY_MAPPED =3D TRUE +STICKY_WRITE =3D TRUE +LOCK_CAP =3D TRUE +LOCK_STATUS =3D TRUE +WRITE_DISABLED_CAP =3D TRUE +WRITE_ENABLED_CAP =3D TRUE +WRITE_STATUS =3D TRUE +WRITE_LOCK_CAP =3D TRUE +WRITE_LOCK_STATUS =3D TRUE +READ_DISABLED_CAP =3D TRUE +READ_ENABLED_CAP =3D TRUE +READ_STATUS =3D TRUE +READ_LOCK_CAP =3D TRUE +READ_LOCK_STATUS =3D TRUE + +INF Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf + +##########################################################################= ########################### +[Rule.Common.SEC] + FILE SEC =3D $(NAMED_GUID) { + TE TE Align =3D Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING =3D"$(MODULE_NAME)" Optional + } diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc b/Platform= /Loongson/LoongArchQemuPkg/Loongson.fdf.inc new file mode 100644 index 0000000000..a1a2d537e3 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc @@ -0,0 +1,21 @@ +## @file +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +DEFINE BLOCK_SIZE =3D 0x1000 + +##########################################################################= ## +# fd total +DEFINE FD_BASE_ADDRESS =3D 0x1c000000 +DEFINE FD_BLOCKS =3D 0x400 +DEFINE FD_SIZE =3D 0x400000 + +##########################################################################= ## +#flash code layout +#Set Sec base address and size in flash +DEFINE SECFV_OFFSET =3D 0x00000000 +DEFINE SECFV_SIZE =3D 0x00010000 diff --git a/Platform/Loongson/LoongArchQemuPkg/Readme.md b/Platform/Loongs= on/LoongArchQemuPkg/Readme.md new file mode 100644 index 0000000000..b0d172f829 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Readme.md @@ -0,0 +1,59 @@ +# Introduction + + This document provides the guideline to build UEFI firmware for Qemu of = LoongArch. + + LoongArch is the general processor architecture of Loongson. + + We can get the latest LoongArch documents or LoongArch tools at https://= github.com/loongson/. + +# How to build (X86 Linux Environment) + + 1. Install LoongArch cross-tools on X86 machines. + Download cross-tools from https://github.com/loongson/ ,Then config cr= oss-tools env. + For Example: + + $ wget https://github.com/loongson/build-tools/releases/latest/downloa= d/loongarch64-clfs-20211202-cross-tools.tar.xz + $ tar -vxf loongarch64-clfs-20211202-cross-tools.tar.xz -C /opt + $ export PATH=3D/opt/cross-tools/bin:$PATH + + 2. Follow edk2-platforms/Readme.md to obtaining source code,And config b= uild env. + For Example: + + $ export WORKSPACE=3D/work/git/tianocore + $ mkdir -p $WORKSPACE + $ cd $WORKSPACE + $ git clone https://github.com/tianocore/edk2.git + $ git submodule update --init + $ git clone https://github.com/tianocore/edk2-platforms.git + $ git submodule update --init + $ git clone https://github.com/tianocore/edk2-non-osi.git + $ export PACKAGES_PATH=3D$PWD/edk2:$PWD/edk2-platforms:$PWD/edk2-non-o= si + + 3. Config cross compiler prefix. + For Example: + + $ export GCC5_LOONGARCH64_PREFIX=3Dloongarch64-unknown-linux-gnu- + + 4.Set up the build environment And build BaseTool. + For Example: + + $. edk2/edksetup.sh + $make -C edk2/BaseTools + + 5.Build platform. + For Exmaple: + + $build --buildtarget=3DDEBUG --tagname=3DGCC5 --arch=3DLOONGARCH64 --= platform=3DPlatform/Loongson/LoongArchQemuPkg/Loongson.dsc + + After a successful build, the resulting images can be found in `Build/{P= latform Name}/{TARGET}_{TOOL_CHAIN_TAG}/FV/QEMU_EFI.fd`. + + A compile script is provided here: + + #!/bin/bash + export WORKSPACE=3D/work/git/tianocore + export PACKAGES_PATH=3D$WORKSPACE/edk2:$WORKSPACE/edk2-platforms + export GCC5_LOONGARCH64_PREFIX=3Dloongarch64-unknown-linux-gnu- + . edk2/edksetup.sh + make -C edk2/BaseTools + build --buildtarget=3DDEBUG --tagname=3DGCC5 --arch=3DLOONGARCH64 --p= latform=3DPlatform/Loongson/LoongArchQemuPkg/Loongson.dsc + diff --git a/Platform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Start.S b/P= latform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Start.S new file mode 100644 index 0000000000..48c044fe28 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Start.S @@ -0,0 +1,76 @@ +#-------------------------------------------------------------------------= ----- +# +# Start for LoongArch +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# @par Glossary: +# - CSR - CPU Status Register +# - EBASE - Exception Base Address +#-------------------------------------------------------------------------= ----- +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif + +#include +#include "LoongArchAsmMacro.h" + + .text + .globl _ModuleEntryPoint +_ModuleEntryPoint: + + /* configure reset ebase */ + li.d T0, 0x1c000000 + csrwr T0, LOONGARCH_CSR_EBASE + + /*disable interrupt*/ + li.d T0, (1 << 2) + csrxchg ZERO, T0, LOONGARCH_CSR_CRMD + + /* read physical cpu number id */ + csrrd T0, LOONGARCH_CSR_CPUNUM + andi T0, T0, 0x3ff + li.d A0, BOOTCORE_ID //0 + bne T0, A0, slave_main + +call_centry: + /*call C function make sure parameter true*/ + li.d A1, FixedPcdGet64(PcdSecPeiTempRamBase) + FixedPcdGet32(PcdSec= PeiTempRamSize) # stack base + li.d A0, FixedPcdGet64(PcdFlashPeiFvBase) # PEI Fv base + move SP, A1 + addi.d SP, SP, -0x8 + bl SecCoreStartupWithStack + +slave_main: + # clear mailbox + li.d T1, LOONGSON_CSR_MAIL_BUF0 + iocsrwr.d ZERO, T1 + + # enable IPI interrupt + li.d T0, (1 << 12) + csrxchg T0, T0, LOONGARCH_CSR_ECFG + +1: + # wait for wakeup + idle 0 + nop + iocsrrd.w T0, T1 + beqz T0, 1b + + # read and clear ipi interrupt + li.d T1, LOONGSON_IOCSR_IPI_STATUS + iocsrrd.w T0, T1 + li.d T1, LOONGSON_IOCSR_IPI_CLEAR + iocsrwr.w T0, T1 + + # disable IPI interrupt + li.d T0, (1 << 12) + csrxchg ZERO, T0, LOONGARCH_CSR_ECFG + + # read mail buf and jump to specified entry + li.d T1, LOONGSON_CSR_MAIL_BUF0 + iocsrrd.d T0, T1 + or RA, T0, ZERO + jirl ZERO, RA, 0x0 diff --git a/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.c b/Platform/Lo= ongson/LoongArchQemuPkg/Sec/SecMain.c new file mode 100644 index 0000000000..73d3a2c1a3 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.c @@ -0,0 +1,510 @@ +/** @file + Main SEC phase code. Transitions to PEI. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** + temporary memory to permanent memory and do stack switching. + + @param[in] PeiServices Pointer to the PEI Services Table. + @param[in] TemporaryMemoryBase Temporary Memory Base address. + @param[in] PermanentMemoryBase Permanent Memory Base address. + @param[in] CopySize The size of memory that needs to be migrated. + + @retval EFI_SUCCESS Migration successful. +**/ +EFI_STATUS +EFIAPI +TemporaryRamMigration ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ); + +EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi =3D { + TemporaryRamMigration +}; + +EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] =3D { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiTemporaryRamSupportPpiGuid, + &mTemporaryRamSupportPpi + }, +}; + +/** + Locates a section within a series of sections + with the specified section type. + + The Instance parameter indicates which instance of the section + type to return. (0 is first instance, 1 is second...) + + @param[in] Sections The sections to search + @param[in] SizeOfSections Total size of all sections + @param[in] SectionType The section type to locate + @param[in] Instance The section instance number + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +FindFfsSectionInstance ( + IN VOID *Sections, + IN UINTN SizeOfSections, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ) +{ + EFI_PHYSICAL_ADDRESS CurrentAddress; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfSections; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; + + // + // Loop through the FFS file sections within the PEI Core FFS file + // + EndOfSection =3D (EFI_PHYSICAL_ADDRESS) (UINTN) Sections; + EndOfSections =3D EndOfSection + SizeOfSections; + for (;;) { + if (EndOfSection =3D=3D EndOfSections) { + break; + } + CurrentAddress =3D (EndOfSection + 3) & ~(3ULL); + if (CurrentAddress >=3D EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + + Section =3D (EFI_COMMON_SECTION_HEADER*) (UINTN) CurrentAddress; + + Size =3D SECTION_SIZE (Section); + if (Size < sizeof (*Section)) { + return EFI_VOLUME_CORRUPTED; + } + + EndOfSection =3D CurrentAddress + Size; + if (EndOfSection > EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + + // + // Look for the requested section type + // + if (Section->Type =3D=3D SectionType) { + if (Instance =3D=3D 0) { + *FoundSection =3D Section; + return EFI_SUCCESS; + } else { + Instance--; + } + } + } + + return EFI_NOT_FOUND; +} + +/** + Locates a section within a series of sections + with the specified section type. + + @param[in] Sections The sections to search + @param[in] SizeOfSections Total size of all sections + @param[in] SectionType The section type to locate + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +FindFfsSectionInSections ( + IN VOID *Sections, + IN UINTN SizeOfSections, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ) +{ + return FindFfsSectionInstance ( + Sections, + SizeOfSections, + SectionType, + 0, + FoundSection + ); +} + +/** + Locates a FFS file with the specified file type and a section + within that file with the specified section type. + + @param[in] Fv The firmware volume to search + @param[in] FileType The file type to locate + @param[in] SectionType The section type to locate + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +FindFfsFileAndSection ( + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, + IN EFI_FV_FILETYPE FileType, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS CurrentAddress; + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; + EFI_FFS_FILE_HEADER *File; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfFile; + + if (Fv->Signature !=3D EFI_FVH_SIGNATURE) { + DEBUG ((DEBUG_ERROR, "FV at %p does not have FV header signature\n", F= v)); + return EFI_VOLUME_CORRUPTED; + } + + CurrentAddress =3D (EFI_PHYSICAL_ADDRESS) (UINTN) Fv; + EndOfFirmwareVolume =3D CurrentAddress + Fv->FvLength; + + // + // Loop through the FFS files in the Boot Firmware Volume + // + for (EndOfFile =3D CurrentAddress + Fv->HeaderLength; ; ) { + + CurrentAddress =3D (EndOfFile + 7) & ~(7ULL); + if (CurrentAddress > EndOfFirmwareVolume) { + return EFI_VOLUME_CORRUPTED; + } + + File =3D (EFI_FFS_FILE_HEADER*) (UINTN) CurrentAddress; + Size =3D *(UINT32*) File->Size & 0xffffff; + if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) { + return EFI_VOLUME_CORRUPTED; + } + + EndOfFile =3D CurrentAddress + Size; + if (EndOfFile > EndOfFirmwareVolume) { + return EFI_VOLUME_CORRUPTED; + } + + // + // Look for the request file type + // + if (File->Type !=3D FileType) { + continue; + } + + Status =3D FindFfsSectionInSections ( + (VOID*) (File + 1), + (UINTN) EndOfFile - (UINTN) (File + 1), + SectionType, + FoundSection + ); + if (!EFI_ERROR (Status) + || (Status =3D=3D EFI_VOLUME_CORRUPTED)) + { + return Status; + } + } +} + +/** + Locates the PEI Core entry point address + + @param[in] Fv The firmware volume to search + @param[out] PeiCoreEntryPoint The entry point of the PEI Core image + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +FindPeiCoreImageBaseInFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, + OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase + ) +{ + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *Section; + + Status =3D FindFfsFileAndSection ( + Fv, + EFI_FV_FILETYPE_PEI_CORE, + EFI_SECTION_PE32, + &Section + ); + if (EFI_ERROR (Status)) { + Status =3D FindFfsFileAndSection ( + Fv, + EFI_FV_FILETYPE_PEI_CORE, + EFI_SECTION_TE, + &Section + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to find PEI Core image\n")); + return Status; + } + } + + *PeiCoreImageBase =3D (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1); + return EFI_SUCCESS; +} + +/** + Find and return Pei Core entry point. + + It also find SEC and PEI Core file debug information. It will report the= m if + remote debug is enabled. + +**/ +VOID +FindAndReportEntryPoints ( + IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr, + OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PeiCoreImageBase =3D 0; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + Status =3D FindPeiCoreImageBaseInFv (*BootFirmwareVolumePtr, &PeiCoreIma= geBase); + ASSERT (Status =3D=3D EFI_SUCCESS); + + ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + + // + // Report PEI Core debug information when remote debug is enabled + // + ImageContext.ImageAddress =3D (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageB= ase; + ImageContext.PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) I= mageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Find PEI Core entry point + // + Status =3D PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase,= (VOID**) PeiCoreEntryPoint); + if (EFI_ERROR (Status)) { + *PeiCoreEntryPoint =3D 0; + } + + return; +} + +/** + Find the peicore entry point and jump to the entry point to execute. + + @param[in] Context The first input parameter of InitializeDebugAgent(= ). + +**/ +VOID +EFIAPI +SecStartupPhase2 ( + IN VOID *Context + ) +{ + EFI_SEC_PEI_HAND_OFF *SecCoreData; + EFI_FIRMWARE_VOLUME_HEADER *BootFv; + EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint; + + SecCoreData =3D (EFI_SEC_PEI_HAND_OFF *) Context; + + // + // Find PEI Core entry point. It will report SEC and Pei Core debug info= rmation if remote debug + // is enabled. + // + BootFv =3D (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolume= Base; + FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint); + SecCoreData->BootFirmwareVolumeBase =3D BootFv; + SecCoreData->BootFirmwareVolumeSize =3D (UINTN) BootFv->FvLength; + + DEBUG ((DEBUG_INFO, "Find Pei EntryPoint=3D%p\n", PeiCoreEntryPoint)); + + // + // Transfer the control to the PEI core + // + DEBUG ((DEBUG_INFO, "SecStartupPhase2 %p\n", PeiCoreEntryPoint)); + + (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDi= spatchTable); + + // + // If we get here then the PEI Core returned, which is not recoverable. + // + ASSERT (FALSE); + CpuDeadLoop (); +} +/** + Entry point to the C language phase of SEC. initialize some temporary me= mory and set up the stack, + the control is transferred to this function. + + @param[in] BootFv The pointer to the PEI FV in memory. + @param[in] TopOfCurrentStack Top of Current Stack. +**/ +VOID +EFIAPI +SecCoreStartupWithStack ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, + IN VOID *TopOfCurrentStack + ) +{ + EFI_SEC_PEI_HAND_OFF SecCoreData; + EFI_FIRMWARE_VOLUME_HEADER *BootPeiFv =3D (EFI_FIRMWARE_VOLUME_HEA= DER*) BootFv; + + DEBUG ((DEBUG_INFO, "Entering C environment\n")); + + ProcessLibraryConstructorList (NULL, NULL); + + DEBUG ((DEBUG_INFO, + "SecCoreStartupWithStack (0x%lx, 0x%lx)\n", + (UINTN)BootFv, + (UINTN)TopOfCurrentStack + )); + DEBUG ((DEBUG_INFO, + "(0x%lx, 0x%lx)\n", + (UINTN) (PcdGet64 (PcdSecPeiTempRamBase)), + (UINTN) (PcdGet32 (PcdSecPeiTempRamSize)) + )); + + // |-------------| <-- TopOfCurrentStack + // | Stack | 32k + // |-------------| + // | Heap | 32k + // |-------------| <-- SecCoreData.TemporaryRamBase + // + + ASSERT ((UINTN) (PcdGet64 (PcdSecPeiTempRamBase) + + PcdGet32 (PcdSecPeiTempRamSize)) =3D=3D + (UINTN) TopOfCurrentStack); + + // + // Initialize SEC hand-off state + // + SecCoreData.DataSize =3D sizeof (EFI_SEC_PEI_HAND_OFF); + + SecCoreData.TemporaryRamSize =3D (UINTN) PcdGet32 (PcdSecPeiTempRa= mSize); + SecCoreData.TemporaryRamBase =3D (VOID *) PcdGet64 (PcdSecPeiTempR= amBase); + + SecCoreData.PeiTemporaryRamBase =3D SecCoreData.TemporaryRamBase; + SecCoreData.PeiTemporaryRamSize =3D SecCoreData.TemporaryRamSize >> 1; + + SecCoreData.StackBase =3D (UINT8 *)SecCoreData.TemporaryRam= Base + SecCoreData.PeiTemporaryRamSize; + SecCoreData.StackSize =3D SecCoreData.TemporaryRamSize >> 1; + + SecCoreData.BootFirmwareVolumeBase =3D BootPeiFv; + SecCoreData.BootFirmwareVolumeSize =3D (UINTN) BootPeiFv->FvLength; + + DEBUG ((DEBUG_INFO, + "&SecCoreData.BootFirmwareVolumeBase=3D%lx SecCoreData.BootFirmwareVol= umeBase=3D%lx\n", + (UINT64)&(SecCoreData.BootFirmwareVolumeBase), + (UINT64) (SecCoreData.BootFirmwareVolumeBase))); + DEBUG ((DEBUG_INFO, + "&SecCoreData.BootFirmwareVolumeSize=3D%lx SecCoreData.BootFirmwareVol= umeSize=3D%lx\n", + (UINT64)&(SecCoreData.BootFirmwareVolumeSize), + (UINT64) (SecCoreData.BootFirmwareVolumeSize))); + + // + // Initialize Debug Agent to support source level debug in SEC/PEI phase= s before memory ready. + // + InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, NULL, NULL); + SecStartupPhase2 (&SecCoreData); +} + +/** + temporary memory to permanent memory and do stack switching. + + @param[in] PeiServices Pointer to the PEI Services Table. + @param[in] TemporaryMemoryBase Temporary Memory Base address. + @param[in] PermanentMemoryBase Permanent Memory Base address. + @param[in] CopySize The size of memory that needs to be migrated. + + @retval EFI_SUCCESS Migration successful. +**/ +EFI_STATUS +EFIAPI +TemporaryRamMigration ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ) +{ + VOID *OldHeap; + VOID *NewHeap; + VOID *OldStack; + VOID *NewStack; + BASE_LIBRARY_JUMP_BUFFER JumpBuffer; + + DEBUG ((DEBUG_INFO, + "TemporaryRamMigration (0x%Lx, 0x%Lx, 0x%Lx)\n", + TemporaryMemoryBase, + PermanentMemoryBase, + (UINT64)CopySize + )); + + OldHeap =3D (VOID*) (UINTN)TemporaryMemoryBase; + NewHeap =3D (VOID*) ((UINTN)PermanentMemoryBase + (CopySize >> 1)); + + OldStack =3D (VOID*) ((UINTN)TemporaryMemoryBase + (CopySize >> 1)); + NewStack =3D (VOID*) (UINTN)PermanentMemoryBase; + +#if 0 + DebugAgentContext.HeapMigrateOffset =3D (UINTN)NewHeap - (UINTN)OldHeap; + DebugAgentContext.StackMigrateOffset =3D (UINTN)NewStack - (UINTN)OldSta= ck; + + OldStatus =3D SaveAndSetDebugTimerInterrupt (FALSE); + InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgent= Context, NULL); +#endif + + // + // Migrate Heap + // + CopyMem (NewHeap, OldHeap, CopySize >> 1); + + // + // Migrate Stack + // + CopyMem (NewStack, OldStack, CopySize >> 1); + + // Use SetJump ()/LongJump () to switch to a new stack. + // + if (SetJump (&JumpBuffer) =3D=3D 0) { + JumpBuffer.SP =3D JumpBuffer.SP - (UINTN)OldStack + (UINTN)NewStack ; + LongJump (&JumpBuffer, (UINTN)-1); + } + + //SaveAndSetDebugTimerInterrupt (OldStatus); + + return EFI_SUCCESS; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf b/Platform/= Loongson/LoongArchQemuPkg/Sec/SecMain.inf new file mode 100644 index 0000000000..03d4ea5b00 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf @@ -0,0 +1,49 @@ +## @file +# SEC Driver +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D SecMain + FILE_GUID =3D 57d02d4f-5a5d-4bfa-b7d6-ba0a4d2c72ce + MODULE_TYPE =3D SEC + VERSION_STRING =3D 1.0 + +[Sources.LOONGARCH64] + LoongArch64/Start.S + SecMain.c + +[Packages] + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + PcdLib + DebugAgentLib + IoLib + PeCoffLib + PeCoffGetEntryPointLib + PeCoffExtraActionLib + +[Ppis] + gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED + +[FixedPcd] + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize + gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress + gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize + + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize diff --git a/Readme.md b/Readme.md index 62876b4b7d..5ae58bca20 100644 --- a/Readme.md +++ b/Readme.md @@ -57,6 +57,7 @@ IA32 | i?86-linux-gnu-* _or_ x86_64-linux-= gnu- IPF | ia64-linux-gnu X64 | x86_64-linux-gnu- RISCV64 | riscv64-unknown-elf- +LOONGARCH64 | loongarch64-unknown-linux-gnu- =20 \* i386, i486, i586 or i686 =20 @@ -71,6 +72,11 @@ RISC-V open source community provides GCC toolchains for [riscv64-unknown-elf](https://github.com/riscv/riscv-gnu-toolchain) compiled to run on x86 Linux. =20 +### GCC for LoongArch +Loonson open source community provides GCC toolchains for +[loongarch64-unknown-elf](https://github.com/loongson/build-tools) +compiled to run on x86 Linux + ### clang Clang does not require separate cross compilers, but it does need a target-specific binutils. These are included with any prepackaged GCC tool= chain @@ -257,6 +263,9 @@ For more information, see the ##### Minnowboard Max/Turbot based on Intel Valleyview2 SoC * [Minnowboard Max](Platform/Intel/Vlv2TbltDevicePkg) =20 +## Loongson +* [LoongArchQemu](Platform/Loongson/LoongArchQemuPkg) + ## Marvell * [Armada 70x0](Platform/Marvell/Armada70x0Db) * [Armada 80x0](Platform/Marvell/Armada80x0Db) --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93892): https://edk2.groups.io/g/devel/message/93892 Mute This Topic: https://groups.io/mt/93715811/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93891+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93891+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299406; cv=none; d=zohomail.com; s=zohoarc; b=WnqH99yixTZXhjPZgW8r+0dM2m9wRNQ3ws4Xj/Kka2jk1lZkqKu61VjPPFJI8mJbF8s2zTWmRHfz4rlG9JP/uXjThPTAlLwEuEveYO3zkT7uUiPYdsFW3tT7IqVAUkd130vT1KGnRih/ynhV1vUDczpmfVNa3GTUBLXGN+suX+8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299406; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=JfbMRRDbmjibpunMzZnNP3lHpCSalqVwlbgLDsDHQtk=; b=BmI4vlxnK1ZLx4yYptdunAnHs7ktYJIfCSUG1auTjrAQLI9j5qpGzCVZq9Ey8Cu/jmcikhKxEWuoA+M6aZ7K0S5RVEj6XGLzhd0hCGm0ZdQrBMf0oMTfQhlFr6CtsjWIiWrCsxFLZeeAB75Fr4ByCwBtxGeG38TJ7UtizoAvkQ0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93891+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299406164134.50862161841167; Thu, 15 Sep 2022 20:36:46 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id uVqEYY1788612xA49Ard7nc0; Thu, 15 Sep 2022 20:36:44 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web11.2175.1663299402822734631 for ; Thu, 15 Sep 2022 20:36:43 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S5; Fri, 16 Sep 2022 11:36:37 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 03/16] Platform/Loongson: Add PeiServicesTablePointerLib. Date: Fri, 16 Sep 2022 11:36:20 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S5 X-Coremail-Antispam: 1UD129KBjvJXoWxZF48AF15Wr18CrW8Xr1xGrg_yoWruF15pw 4UGF4kKr45JryIgryYqa15CFW5AFsrCr95Crs7XF15Cw1kZry0qr12vFyFkF1rua1rAw1I grWFkw4Uua4UXF7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: Pzqai7v6ae2syFlkO34Go93Dx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299404; bh=QbgSGNA79pkkux4gpudpj7fD6WDMjADLbLdM+6mczOA=; h=Cc:Date:From:Reply-To:Subject:To; b=kiHBBRak7y7FK9ner0ikNn4Nfj2FWWIGG4tFn9sVbMDlSY7yx3KAdMo9g+l1vQ3IcTL VOW5etxi4WEF9R+d/mJWkDTdpfMHAHBKykmny/29cbszhxat9IwcgpulMrOKhRmk58W8Y UwTyKI4+GFkX2CK8P6+s8ojd6D5F/dQYBlQ= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299408292100025 Content-Type: text/plain; charset="utf-8" Use a register to save PeiServicesTable pointer, This lib Provides PeiServicesTable pointer saving and retrieval services. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../PeiServicesTablePointer.c | 78 +++++++++++++++++++ .../PeiServicesTablePointerLib.inf | 32 ++++++++ 2 files changed, 110 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PeiServicesT= ablePointerLib/PeiServicesTablePointer.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PeiServicesT= ablePointerLib/PeiServicesTablePointerLib.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PeiServicesTablePoi= nterLib/PeiServicesTablePointer.c b/Platform/Loongson/LoongArchQemuPkg/Libr= ary/PeiServicesTablePointerLib/PeiServicesTablePointer.c new file mode 100644 index 0000000000..068960d4ce --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PeiServicesTablePointerLib= /PeiServicesTablePointer.c @@ -0,0 +1,78 @@ +/** @file + PEI Services Table Pointer Library. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include "Library/Cpu.h" + +/** + Caches a pointer PEI Services Table. + + Caches the pointer to the PEI Services Table specified by PeiServicesTab= lePointer + in a platform specific manner. + + If PeiServicesTablePointer is NULL, then ASSERT (). + + @param PeiServicesTablePointer The address of PeiServices pointer. +**/ +VOID +EFIAPI +SetPeiServicesTablePointer ( + IN CONST EFI_PEI_SERVICES ** PeiServicesTablePointer + ) +{ + LOONGARCH_CSR_WRITEQ ((UINTN)PeiServicesTablePointer, LOONGARCH_CSR_KS0); +} + +/** + Retrieves the cached value of the PEI Services Table pointer. + + Returns the cached value of the PEI Services Table pointer in a CPU spec= ific manner + as specified in the CPU binding section of the Platform Initialization P= re-EFI + Initialization Core Interface Specification. + + If the cached PEI Services Table pointer is NULL, then ASSERT (). + + @return The pointer to PeiServices. +**/ +CONST EFI_PEI_SERVICES ** +EFIAPI +GetPeiServicesTablePointer ( + VOID + ) +{ + UINTN val; + + LOONGARCH_CSR_READQ (val, LOONGARCH_CSR_KS0); + return (CONST EFI_PEI_SERVICES **)val; +} + +/** +Perform CPU specific actions required to migrate the PEI Services Table +pointer from temporary RAM to permanent RAM. + +For IA32 CPUs, the PEI Services Table pointer is stored in the 4 bytes +immediately preceding the Interrupt Descriptor Table (IDT) in memory. +For X64 CPUs, the PEI Services Table pointer is stored in the 8 bytes +immediately preceding the Interrupt Descriptor Table (IDT) in memory. +For Itanium and ARM CPUs, a the PEI Services Table Pointer is stored in +a dedicated CPU register. This means that there is no memory storage +associated with storing the PEI Services Table pointer, so no additional +migration actions are required for Itanium or ARM CPUs. + +**/ +VOID +EFIAPI +MigratePeiServicesTablePointer ( +VOID +) +{ + return; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PeiServicesTablePoi= nterLib/PeiServicesTablePointerLib.inf b/Platform/Loongson/LoongArchQemuPkg= /Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf new file mode 100644 index 0000000000..6fe76d1351 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PeiServicesTablePointerLib= /PeiServicesTablePointerLib.inf @@ -0,0 +1,32 @@ +## @file +# PEI Services Table Pointer Library. +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PeiServicesTablePointerLib + FILE_GUID =3D C3C9C4ED-EB8A-4548-BE1B-ABB0B6F35B1E + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D PeiServicesTablePointerLib|PEIM PEI_C= ORE SEC + +# +# VALID_ARCHITECTURES =3D LOONGARCH64 +# + +[Sources] + PeiServicesTablePointer.c + +[Packages] + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + +[Pcd] + --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93891): https://edk2.groups.io/g/devel/message/93891 Mute This Topic: https://groups.io/mt/93715809/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93887+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93887+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299403; cv=none; d=zohomail.com; s=zohoarc; b=Nz68/I7ee8JxwmAqK/opdhM9Ni1hYE/r9R9KuYbK7YqztKPD3QaEyPvzfi5hf0T7J2gB/q1J0OszXkudNBzPdCMddZhZqV2QWm+Fw8iNXyT0sy6W2Uo90VjuoGw1/dlx2rKNpVFsr0YF3IrY+XvRId60a8FSN3kpNAHHBgYorZk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299403; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=XXIZyIHZyS2b2RH2UQ9KNSmYJQuLxL8kRzEXTEt9hNE=; b=HiazQ1EMn3fe4e9SO7Npqx5CuUHBFLuGKitLS7eWPdLg2zMQIuajm4qqmZeYmWUQdA6jVMEyPPykVzLsg5qZ4lwrSoUR+hB3w+cHTUs5HUqtJNhaveFU5CydppqgRbuOcnFOqJH8P2bD3lobnRzC63O7NvrUc5uO5GZDGWWF7no= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93887+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299403326752.8295176982772; Thu, 15 Sep 2022 20:36:43 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 9W9wYY1788612x9Ep9qZtLgO; Thu, 15 Sep 2022 20:36:42 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web09.2231.1663299400296733506 for ; Thu, 15 Sep 2022 20:36:41 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S6; Fri, 16 Sep 2022 11:36:37 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 04/16] Platform/Loongson: Add QemuFwCfgLib. Date: Fri, 16 Sep 2022 11:36:21 +0800 Message-Id: <345a9df259f592aba9b1518b0bdce4eb03a0ad07.1663298005.git.lixianglai@loongson.cn> In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S6 X-Coremail-Antispam: 1UD129KBjvAXoWfuryfCw1xtF13XFyfZrWUJwb_yoW5Gr1xZo W8XF97Aw15Kw4rW34IkFn3W3y8JFW0gr4FqFWrAF4jq3Z8tF4Y9FW7ta4UWFn3Aw1rt34k A3yrX3yfZFZ2vrs5n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: nXYgl0mfUkRpQlTwASr1olhax1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299402; bh=P+/va7vMD9Ah17QmBE6bjjqlzeHCVvGtzadNCnHWWn4=; h=Cc:Date:From:Reply-To:Subject:To; b=kB1mpUHZngL3sGxZ3cVGCCgQeSMYjoc36np0C0WLs+siRygZkD1JBC57iOn1mNzVbNt uApeXip+zZyJoEkks4PTm0psrVL6KWR8G4MhB34lSusgq8tfIFZU/ubw07gza6sUkbH+G uhP3GcYdr58gg2JLahhFr3iAzqhbFjMtpoc= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299404332100001 Content-Type: text/plain; charset="utf-8" QemuFwCfgLib for PEI phase. This library obtains the QemuFWCfg base address by directly parsing the fdt, and reads and writes the data in the QemuFWCfg by operating on the QemuFWCfg base address. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../Include/IndustryStandard/QemuFwCfg.h | 95 ++++ .../Include/Library/QemuFwCfgLib.h | 193 +++++++ .../QemuFwCfgLib/QemuFwCfgLibInternal.h | 64 +++ .../Library/QemuFwCfgLib/QemuFwCfgPei.c | 119 +++++ .../Library/QemuFwCfgLib/QemuFwCfgPeiLib.c | 477 ++++++++++++++++++ .../Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf | 44 ++ 6 files changed, 992 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/IndustryStan= dard/QemuFwCfg.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/Qemu= FwCfgLib.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib= /QemuFwCfgLibInternal.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib= /QemuFwCfgPei.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib= /QemuFwCfgPeiLib.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib= /QemuFwCfgPeiLib.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/IndustryStandard/Qe= muFwCfg.h b/Platform/Loongson/LoongArchQemuPkg/Include/IndustryStandard/Qem= uFwCfg.h new file mode 100644 index 0000000000..a028ca1124 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/IndustryStandard/QemuFwCfg= .h @@ -0,0 +1,95 @@ +/** @file + Macro and type definitions corresponding to the QEMU fw_cfg interface. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - FW - FireWare + - CFG - Configure + - FNAME - File Name + - CTL - Contorl +**/ + +#ifndef QEMU_FW_CFG_H_ +#define QEMU_FW_CFG_H_ + +#include + +// +// The size, in bytes, of names of firmware configuration files, including= at +// least one terminating NUL byte. +// +#define QEMU_FW_CFG_FNAME_SIZE 56 + +// +// If the following bit is set in the UINT32 fw_cfg revision / feature bit= map +// -- read from key 0x0001 with the basic IO Port or MMIO method --, then = the +// DMA interface is available. +// +#define FW_CFG_F_DMA BIT1 + +// +// Macros for the FW_CFG_DMA_ACCESS.Control bitmap (in native encoding). +// +#define FW_CFG_DMA_CTL_ERROR BIT0 +#define FW_CFG_DMA_CTL_READ BIT1 +#define FW_CFG_DMA_CTL_SKIP BIT2 +#define FW_CFG_DMA_CTL_SELECT BIT3 +#define FW_CFG_DMA_CTL_WRITE BIT4 + +// +// The fw_cfg registers can be found at these IO Ports, on the IO-mapped +// platforms (Ia32 and X64). +// +#define FW_CFG_IO_SELECTOR 0x510 +#define FW_CFG_IO_DATA 0x511 +#define FW_CFG_IO_DMA_ADDRESS 0x514 + +// +// Numerically defined keys. +// +typedef enum { + QemuFwCfgItemSignature =3D 0x0000, + QemuFwCfgItemInterfaceVersion =3D 0x0001, + QemuFwCfgItemSystemUuid =3D 0x0002, + QemuFwCfgItemRamSize =3D 0x0003, + QemuFwCfgItemGraphicsEnabled =3D 0x0004, + QemuFwCfgItemSmpCpuCount =3D 0x0005, + QemuFwCfgItemMachineId =3D 0x0006, + QemuFwCfgItemKernelAddress =3D 0x0007, + QemuFwCfgItemKernelSize =3D 0x0008, + QemuFwCfgItemKernelCommandLine =3D 0x0009, + QemuFwCfgItemInitrdAddress =3D 0x000a, + QemuFwCfgItemInitrdSize =3D 0x000b, + QemuFwCfgItemBootDevice =3D 0x000c, + QemuFwCfgItemNumaData =3D 0x000d, + QemuFwCfgItemBootMenu =3D 0x000e, + QemuFwCfgItemMaximumCpuCount =3D 0x000f, + QemuFwCfgItemKernelEntry =3D 0x0010, + QemuFwCfgItemKernelData =3D 0x0011, + QemuFwCfgItemInitrdData =3D 0x0012, + QemuFwCfgItemCommandLineAddress =3D 0x0013, + QemuFwCfgItemCommandLineSize =3D 0x0014, + QemuFwCfgItemCommandLineData =3D 0x0015, + QemuFwCfgItemKernelSetupAddress =3D 0x0016, + QemuFwCfgItemKernelSetupSize =3D 0x0017, + QemuFwCfgItemKernelSetupData =3D 0x0018, + QemuFwCfgItemFileDir =3D 0x0019, + +} FIRMWARE_CONFIG_ITEM; + +// +// Communication structure for the DMA access method. All fields are encod= ed in +// big endian. +// +#pragma pack (1) +typedef struct { + UINT32 Control; + UINT32 Length; + UINT64 Address; +} FW_CFG_DMA_ACCESS; +#pragma pack () + +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLi= b.h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h new file mode 100644 index 0000000000..6b42cf3073 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h @@ -0,0 +1,193 @@ +/** @file + QEMU/KVM Firmware Configuration access + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - FW or Fw - Firmware + - Cfg - Configure +**/ + +#ifndef QEMU_FW_CFG_LIB_ +#define QEMU_FW_CFG_LIB_ + +#include + +typedef enum { + EfiAcpiAddressRangeMemory =3D 1, + EfiAcpiAddressRangeReserved =3D 2, + EfiAcpiAddressRangeACPI =3D 3, + EfiAcpiAddressRangeNVS =3D 4 +} EFI_ACPI_MEMORY_TYPE; + +typedef struct { + UINT64 BaseAddr; + UINT64 Length; + UINT32 Type; + UINT32 Reserved; +} LOONGARCH_MEMMAP_ENTRY; + +/** + Returns a boolean indicating if the firmware configuration interface + is available or not. + + This function may change fw_cfg state. + + @retval TRUE The interface is available + @retval FALSE The interface is not available + +**/ +BOOLEAN +EFIAPI +QemuFwCfgIsAvailable ( + VOID + ); + + +/** + Selects a firmware configuration item for reading. + + Following this call, any data read from this item will start from + the beginning of the configuration item's data. + + @param[in] QemuFwCfgItem - Firmware Configuration item to read + +**/ +VOID +EFIAPI +QemuFwCfgSelectItem ( + IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem + ); + + +/** + Reads firmware configuration bytes into a buffer + + If called multiple times, then the data read will + continue at the offset of the firmware configuration + item where the previous read ended. + + @param[in] Size - Size in bytes to read + @param[in] Buffer - Buffer to store data into + +**/ +VOID +EFIAPI +QemuFwCfgReadBytes ( + IN UINTN Size, + IN VOID *Buffer OPTIONAL + ); + + +/** + Writes firmware configuration bytes from a buffer + + If called multiple times, then the data written will + continue at the offset of the firmware configuration + item where the previous write ended. + + @param[in] Size - Size in bytes to write + @param[in] Buffer - Buffer to read data from + +**/ +VOID +EFIAPI +QemuFwCfgWriteBytes ( + IN UINTN Size, + IN VOID *Buffer + ); + + +/** + Skip bytes in the firmware configuration item. + + Increase the offset of the firmware configuration item without transferr= ing + bytes between the item and a caller-provided buffer. Subsequent read, wr= ite + or skip operations will commence at the increased offset. + + @param[in] Size Number of bytes to skip. +**/ +VOID +EFIAPI +QemuFwCfgSkipBytes ( + IN UINTN Size + ); + + +/** + Reads a UINT8 firmware configuration value + + @retval Value of Firmware Configuration item read + +**/ +UINT8 +EFIAPI +QemuFwCfgRead8 ( + VOID + ); + + +/** + Reads a UINT16 firmware configuration value + + @retval Value of Firmware Configuration item read + +**/ +UINT16 +EFIAPI +QemuFwCfgRead16 ( + VOID + ); + + +/** + Reads a UINT32 firmware configuration value + + @retval Value of Firmware Configuration item read + +**/ +UINT32 +EFIAPI +QemuFwCfgRead32 ( + VOID + ); + + +/** + Reads a UINT64 firmware configuration value + + @retval Value of Firmware Configuration item read + +**/ +UINT64 +EFIAPI +QemuFwCfgRead64 ( + VOID + ); + + +/** + Find the configuration item corresponding to the firmware configuration = file. + + @param[in] Name - Name of file to look up. + @param[out] Item - Configuration item corresponding to the file, to be p= assed + to QemuFwCfgSelectItem (). + @param[out] Size - Number of bytes in the file. + + @retval RETURN_SUCCESS If file is found. + RETURN_NOT_FOUND If file is not found. + RETURN_UNSUPPORTED If firmware configuration is unavailable. + +**/ +RETURN_STATUS +EFIAPI +QemuFwCfgFindFile ( + IN CONST CHAR8 *Name, + OUT FIRMWARE_CONFIG_ITEM *Item, + OUT UINTN *Size + ); + +#endif + diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFw= CfgLibInternal.h b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/= QemuFwCfgLibInternal.h new file mode 100644 index 0000000000..33eeb927dd --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibI= nternal.h @@ -0,0 +1,64 @@ +/** @file + fw_cfg library implementation. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - FwCfg - firmWare Configure +**/ + +#ifndef QEMU_FW_CFG_LIB_INTERNAL_H_ +#define QEMU_FW_CFG_LIB_INTERNAL_H_ + +/** + Returns a boolean indicating if the firmware configuration interface is + available for library-internal purposes. + + This function never changes fw_cfg state. + + @retval TRUE The interface is available internally. + @retval FALSE The interface is not available internally. +**/ +BOOLEAN +InternalQemuFwCfgIsAvailable ( + VOID + ); + + +/** + Returns a boolean indicating whether QEMU provides the DMA-like access m= ethod + for fw_cfg. + + @retval TRUE The DMA-like access method is available. + @retval FALSE The DMA-like access method is unavailable. +**/ +BOOLEAN +InternalQemuFwCfgDmaIsAvailable ( + VOID + ); + +/** + Transfer an array of bytes, or skip a number of bytes, using the DMA + interface. + + @param[in] Size Size in bytes to transfer or skip. + + @param[in,out] Buffer Buffer to read data into or write data from. Ign= ored, + and may be NULL, if Size is zero, or Control is + FW_CFG_DMA_CTL_SKIP. + + @param[in] Control One of the following: + FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buff= er. + FW_CFG_DMA_CTL_READ - read from fw_cfg into Buf= fer. + FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg. +**/ +VOID +InternalQemuFwCfgDmaBytes ( + IN UINT32 Size, + IN OUT VOID *Buffer OPTIONAL, + IN UINT32 Control + ); + +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFw= CfgPei.c b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCf= gPei.c new file mode 100644 index 0000000000..91995c90b5 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c @@ -0,0 +1,119 @@ +/** @file + fw_cfg library implementation. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - FwCfg - firmWare Configure +**/ + +#include +#include +#include + +#include "QemuFwCfgLibInternal.h" + +/** + Returns a boolean indicating if the firmware configuration interface + is available or not. + + This function may change fw_cfg state. + + @retval TRUE The interface is available + @retval FALSE The interface is not available + +**/ +BOOLEAN +EFIAPI +QemuFwCfgIsAvailable ( + VOID + ) +{ + UINT32 Signature; + UINT32 Revision; + + QemuFwCfgSelectItem (QemuFwCfgItemSignature); + Signature =3D QemuFwCfgRead32 (); + DEBUG ((DEBUG_INFO, "FW CFG Signature: 0x%x\n", Signature)); + QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion); + Revision =3D QemuFwCfgRead32 (); + DEBUG ((DEBUG_INFO, "FW CFG Revision: 0x%x\n", Revision)); + if ((Signature !=3D SIGNATURE_32 ('Q', 'E', 'M', 'U')) + || (Revision < 1)) + { + DEBUG ((DEBUG_INFO, "QemuFwCfg interface not supported.\n")); + return FALSE; + } + + DEBUG ((DEBUG_INFO, "QemuFwCfg interface is supported.\n")); + return TRUE; +} + + +/** + Returns a boolean indicating if the firmware configuration interface is + available for library-internal purposes. + + This function never changes fw_cfg state. + + @retval TRUE The interface is available internally. + @retval FALSE The interface is not available internally. +**/ +BOOLEAN +InternalQemuFwCfgIsAvailable ( + VOID + ) +{ + // + // We always return TRUE, because the consumer of this library ought to = have + // called QemuFwCfgIsAvailable before making other calls which would hit= this + // path. + // + return TRUE; +} + +/** + Returns a boolean indicating whether QEMU provides the DMA-like access m= ethod + for fw_cfg. + + @retval TRUE The DMA-like access method is available. + @retval FALSE The DMA-like access method is unavailable. +**/ +BOOLEAN +InternalQemuFwCfgDmaIsAvailable ( + VOID + ) +{ + return FALSE; +} + +/** + Transfer an array of bytes, or skip a number of bytes, using the DMA + interface. + + @param[in] Size Size in bytes to transfer or skip. + + @param[in, out] Buffer Buffer to read data into or write data from. Ig= nored, + and may be NULL, if Size is zero, or Control is + FW_CFG_DMA_CTL_SKIP. + + @param[in] Control One of the following: + FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buff= er. + FW_CFG_DMA_CTL_READ - read from fw_cfg into Buf= fer. + FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg. +**/ +VOID +InternalQemuFwCfgDmaBytes ( + IN UINT32 Size, + IN OUT VOID *Buffer OPTIONAL, + IN UINT32 Control + ) +{ + // + // We should never reach here + // + ASSERT (FALSE); + CpuDeadLoop (); +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFw= CfgPeiLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuF= wCfgPeiLib.c new file mode 100644 index 0000000000..2bbaa9ed35 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiL= ib.c @@ -0,0 +1,477 @@ +/** @file + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - FwCfg - firmWare Configure + - CTL - Control +**/ + +#include "Uefi.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "QemuFwCfgLibInternal.h" + +STATIC UINTN mFwCfgSelectorAddress; +STATIC UINTN mFwCfgDataAddress; +/** + To get firmware configure selector address. + + @param VOID + + @retval firmware configure selector address +**/ +UINTN +EFIAPI +QemuGetFwCfgSelectorAddress ( + VOID + ) +{ + UINTN FwCfgSelectorAddress =3D mFwCfgSelectorAddress; + if (FwCfgSelectorAddress =3D=3D 0) { + FwCfgSelectorAddress =3D (UINTN)PcdGet64 (PcdFwCfgSelectorAddress); + } + return FwCfgSelectorAddress; +} +/** + To get firmware configure Data address. + + @param VOID + + @retval firmware configure data address +**/ +UINTN +EFIAPI +QemuGetFwCfgDataAddress ( + VOID + ) +{ + UINTN FwCfgDataAddress =3D mFwCfgDataAddress; + if (FwCfgDataAddress =3D=3D 0) { + FwCfgDataAddress =3D (UINTN)PcdGet64 (PcdFwCfgDataAddress); + } + return FwCfgDataAddress; +} +/** + Selects a firmware configuration item for reading. + + Following this call, any data read from this item will start from + the beginning of the configuration item's data. + + @param[in] QemuFwCfgItem - Firmware Configuration item to read + +**/ +VOID +EFIAPI +QemuFwCfgSelectItem ( + IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem + ) +{ + UINTN FwCfgSelectorAddress; + FwCfgSelectorAddress =3D QemuGetFwCfgSelectorAddress (); + MmioWrite16 (FwCfgSelectorAddress, SwapBytes16((UINT16) (UINTN)QemuFwCfg= Item)); +} + +/** + Slow READ_BYTES_FUNCTION. + + @param[in] The size of the data to be read. + @param[in] Buffer The buffer that stores the readout data. +**/ +VOID +EFIAPI +MmioReadBytes ( + IN UINTN Size, + IN VOID *Buffer OPTIONAL + ) +{ + UINTN Left; + UINT8 *Ptr; + UINT8 *End; + UINTN FwCfgDataAddress; + Left =3D Size & 7; + + Size -=3D Left; + Ptr =3D Buffer; + End =3D Ptr + Size; + FwCfgDataAddress =3D QemuGetFwCfgDataAddress (); + while (Ptr < End) { + *(UINT64 *)Ptr =3D MmioRead64 (FwCfgDataAddress); + Ptr +=3D 8; + } + if (Left & 4) { + *(UINT32 *)Ptr =3D MmioRead32 (FwCfgDataAddress); + Ptr +=3D 4; + } + if (Left & 2) { + *(UINT16 *)Ptr =3D MmioRead16 (FwCfgDataAddress); + Ptr +=3D 2; + } + if (Left & 1) { + *Ptr =3D MmioRead8 (FwCfgDataAddress); + } +} + +/** + Slow WRITE_BYTES_FUNCTION. + + @param[in] The size of the data to be write. + @param[in] Buffer The buffer that stores the writein data. +**/ +VOID +EFIAPI +MmioWriteBytes ( + IN UINTN Size, + IN VOID *Buffer OPTIONAL + ) +{ + UINTN Idx; + UINTN FwCfgDataAddress; + FwCfgDataAddress =3D QemuGetFwCfgDataAddress (); + for (Idx =3D 0; Idx < Size; ++Idx) { + MmioWrite8 (FwCfgDataAddress, ((UINT8 *)Buffer)[Idx]); + } +} + +/** + Reads firmware configuration bytes into a buffer + + @param[in] Size - Size in bytes to read + @param[in] Buffer - Buffer to store data into (OPTIONAL if Size is 0) + +**/ +VOID +EFIAPI +InternalQemuFwCfgReadBytes ( + IN UINTN Size, + IN VOID *Buffer OPTIONAL + ) +{ + if ((InternalQemuFwCfgDmaIsAvailable ()) + && (Size <=3D MAX_UINT32)) + { + InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_READ); + return; + } + MmioReadBytes (Size, Buffer); +} + + +/** + Reads firmware configuration bytes into a buffer + + If called multiple times, then the data read will + continue at the offset of the firmware configuration + item where the previous read ended. + + @param[in] Size - Size in bytes to read + @param[in] Buffer - Buffer to store data into +**/ +VOID +EFIAPI +QemuFwCfgReadBytes ( + IN UINTN Size, + IN VOID *Buffer + ) +{ + if (InternalQemuFwCfgIsAvailable ()) { + InternalQemuFwCfgReadBytes (Size, Buffer); + } else { + ZeroMem (Buffer, Size); + } +} + +/** + Write firmware configuration bytes from a buffer + + If called multiple times, then the data written will + continue at the offset of the firmware configuration + item where the previous write ended. + + @param[in] Size - Size in bytes to write + @param[in] Buffer - Buffer to read data from +**/ +VOID +EFIAPI +QemuFwCfgWriteBytes ( + IN UINTN Size, + IN VOID *Buffer + ) +{ + if (InternalQemuFwCfgIsAvailable ()) { + if ((InternalQemuFwCfgDmaIsAvailable ()) + && (Size <=3D MAX_UINT32)) + { + InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_WRIT= E); + return; + } + MmioWriteBytes (Size, Buffer); + } +} + + +/** + Skip bytes in the firmware configuration item. + + Increase the offset of the firmware configuration item without transferr= ing + bytes between the item and a caller-provided buffer. Subsequent read, wr= ite + or skip operations will commence at the increased offset. + + @param[in] Size Number of bytes to skip. +**/ +VOID +EFIAPI +QemuFwCfgSkipBytes ( + IN UINTN Size + ) +{ + UINTN ChunkSize; + UINT8 SkipBuffer[256]; + + if (!InternalQemuFwCfgIsAvailable ()) { + return; + } + + if ((InternalQemuFwCfgDmaIsAvailable ()) + && (Size <=3D MAX_UINT32)) + { + InternalQemuFwCfgDmaBytes ((UINT32)Size, NULL, FW_CFG_DMA_CTL_SKIP); + return; + } + + // + // Emulate the skip by reading data in chunks, and throwing it away. The + // implementation below is suitable even for phases where RAM or dynamic + // allocation is not available or appropriate. It also doesn't affect the + // static data footprint for client modules. Large skips are not expecte= d, + // therefore this fallback is not performance critical. The size of + // SkipBuffer is thought not to exert a large pressure on the stack in a= ny + // phase. + // + while (Size > 0) { + ChunkSize =3D MIN (Size, sizeof SkipBuffer); + MmioReadBytes (ChunkSize, SkipBuffer); + Size -=3D ChunkSize; + } +} + + +/** + Reads a UINT8 firmware configuration value + + @return Value of Firmware Configuration item read + +**/ +UINT8 +EFIAPI +QemuFwCfgRead8 ( + VOID + ) +{ + UINT8 Result; + + QemuFwCfgReadBytes (sizeof (Result), &Result); + + return Result; +} + + +/** + Reads a UINT16 firmware configuration value + + @return Value of Firmware Configuration item read + +**/ +UINT16 +EFIAPI +QemuFwCfgRead16 ( + VOID + ) +{ + UINT16 Result; + + QemuFwCfgReadBytes (sizeof (Result), &Result); + + return Result; +} + + +/** + Reads a UINT32 firmware configuration value + + @return Value of Firmware Configuration item read + +**/ +UINT32 +EFIAPI +QemuFwCfgRead32 ( + VOID + ) +{ + UINT32 Result; + + QemuFwCfgReadBytes (sizeof (Result), &Result); + + return Result; +} + + +/** + Reads a UINT64 firmware configuration value + + @return Value of Firmware Configuration item read + +**/ +UINT64 +EFIAPI +QemuFwCfgRead64 ( + VOID + ) +{ + UINT64 Result; + + QemuFwCfgReadBytes (sizeof (Result), &Result); + + return Result; +} + + +/** + Find the configuration item corresponding to the firmware configuration = file. + + @param[in] Name - Name of file to look up. + @param[out] Item - Configuration item corresponding to the file, to be p= assed + to QemuFwCfgSelectItem (). + @param[out] Size - Number of bytes in the file. + + @return RETURN_SUCCESS If file is found. + RETURN_NOT_FOUND If file is not found. + RETURN_UNSUPPORTED If firmware configuration is unavailable. + +**/ +RETURN_STATUS +EFIAPI +QemuFwCfgFindFile ( + IN CONST CHAR8 *Name, + OUT FIRMWARE_CONFIG_ITEM *Item, + OUT UINTN *Size + ) +{ + UINT32 Count; + UINT32 Idx; + + if (!InternalQemuFwCfgIsAvailable ()) { + return RETURN_UNSUPPORTED; + } + + QemuFwCfgSelectItem (QemuFwCfgItemFileDir); + Count =3D SwapBytes32 (QemuFwCfgRead32 ()); + + for (Idx =3D 0; Idx < Count; ++Idx) { + UINT32 FileSize; + UINT16 FileSelect; + CHAR8 FileName[QEMU_FW_CFG_FNAME_SIZE]; + + FileSize =3D QemuFwCfgRead32 (); + FileSelect =3D QemuFwCfgRead16 (); + QemuFwCfgRead16 (); // skip the field called "reserved" + InternalQemuFwCfgReadBytes (sizeof (FileName), FileName); + + if (AsciiStrCmp (Name, FileName) =3D=3D 0) { + *Item =3D SwapBytes16 (FileSelect); + *Size =3D SwapBytes32 (FileSize); + return RETURN_SUCCESS; + } + } + + return RETURN_NOT_FOUND; +} + +/** + firmware config initialize. + + @param VOID + + @return RETURN_SUCCESS Initialization succeeded. +**/ +RETURN_STATUS +EFIAPI +QemuFwCfgInitialize ( + VOID + ) +{ + VOID *DeviceTreeBase; + INT32 Node; + INT32 Prev; + CONST CHAR8 *Type; + INT32 Len; + CONST UINT64 *RegProp; + UINT64 FwCfgSelectorAddress; + UINT64 FwCfgDataAddress; + UINT64 FwCfgDataSize; + RETURN_STATUS PcdStatus; + + DeviceTreeBase =3D (VOID *) (UINTN)PcdGet64 (PcdDeviceTreeBase); + ASSERT (DeviceTreeBase !=3D NULL); + // + // Make sure we have a valid device tree blob + // + ASSERT (fdt_check_header (DeviceTreeBase) =3D=3D 0); + + for (Prev =3D 0;; Prev =3D Node) { + Node =3D fdt_next_node (DeviceTreeBase, Prev, NULL); + if (Node < 0) { + break; + } + + // + // Check for memory node + // + Type =3D fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); + if ((Type) + && (AsciiStrnCmp (Type, "qemu,fw-cfg-mmio", Len) =3D=3D 0)) + { + // + // Get the 'reg' property of this node. For now, we will assume + // two 8 byte quantities for base and size, respectively. + // + RegProp =3D fdt_getprop (DeviceTreeBase, Node, "reg", &Len); + if ((RegProp !=3D 0) + && (Len =3D=3D (2 * sizeof (UINT64)))) + { + FwCfgDataAddress =3D SwapBytes64 (RegProp[0]); + FwCfgDataSize =3D 8; + FwCfgSelectorAddress =3D FwCfgDataAddress + FwCfgDataSize; + + mFwCfgSelectorAddress =3D FwCfgSelectorAddress; + mFwCfgDataAddress =3D FwCfgDataAddress; + + PcdStatus =3D PcdSet64S ( + PcdFwCfgSelectorAddress, + FwCfgSelectorAddress + ); + ASSERT_RETURN_ERROR (PcdStatus); + PcdStatus =3D PcdSet64S ( + PcdFwCfgDataAddress, + FwCfgDataAddress + ); + ASSERT_RETURN_ERROR (PcdStatus); + break; + } else { + DEBUG ((DEBUG_ERROR, "%a: Failed to parse FDT QemuCfg node\n", + __FUNCTION__)); + break; + } + } + } + return RETURN_SUCCESS; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFw= CfgPeiLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/Qem= uFwCfgPeiLib.inf new file mode 100644 index 0000000000..e6df7d9120 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiL= ib.inf @@ -0,0 +1,44 @@ +## @file +# initialized fw_cfg library. +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D QemuFwCfgSecLib + FILE_GUID =3D cdf9a9d5-7422-4dcb-b41d-607151ad320b + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D QemuFwCfgLib|PEIM + + CONSTRUCTOR =3D QemuFwCfgInitialize + + +[Sources] + QemuFwCfgLibInternal.h + QemuFwCfgPeiLib.c + QemuFwCfgPei.c + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + IoLib + MemoryAllocationLib + FdtLib + PcdLib + +[Pcd] + gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase + gLoongArchQemuPkgTokenSpaceGuid.PcdFwCfgSelectorAddress + gLoongArchQemuPkgTokenSpaceGuid.PcdFwCfgDataAddress --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93887): https://edk2.groups.io/g/devel/message/93887 Mute This Topic: https://groups.io/mt/93715805/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93894+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93894+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299406; cv=none; d=zohomail.com; s=zohoarc; b=c3nKcxUA25sQdW+/gaPYzCZJYG7ML1M2euyw4VC9WsXxz21LUSYC14zPZ0voXQmBQl2tNbb53Px3k7ZCs0f22OHWN6eE297qtasjF0TbScIXl32yuTmaeNP83ociOk3ZtmJ3Ceui3IOeV4vz5NcZJWzRdsAd6krMtO+VwgAhAvc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299406; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=xOInyrYHrvbEasaWPb0LSUOylOX/kxqZz4pUVsuycHk=; b=QlC3DYDWWL3ykYIPlIVCv4dZV2K+vEqQmxuL2O1O/6LRDHejKVFHy0llkcOXBOLN5bZ6nRBe7AeUgRy3wMPZoaFA4Y1S1qipjI5m451jX6ZYc4rUmFJJ2eJWyLDGv7T7cn+r+kKYwMbSrI078XyyxIs4na+5Kcnxg8IEwK7DBR0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93894+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299406138638.3374808502365; Thu, 15 Sep 2022 20:36:46 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id bXYSYY1788612x6RFHhraf1d; Thu, 15 Sep 2022 20:36:45 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web11.2174.1663299400398979630 for ; Thu, 15 Sep 2022 20:36:44 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S7; Fri, 16 Sep 2022 11:36:37 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 05/16] Platform/Loongson: Add MmuLib. Date: Fri, 16 Sep 2022 11:36:22 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S7 X-Coremail-Antispam: 1UD129KBjvAXoWDXFW8WryxGw1rtrW8JFyrJFb_yoW7WFy8Ko WY9F4rCw4UJw4rZr4rCwn2gay8tFsYv39xXr1FvF4jqFsYvrs0kFWUtayUJ34fZ34Svrnx GrykXaykAFWSgr1rn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: SBIrsbRdxMoAuhBD2eDKf4trx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299405; bh=Wr9/a67pHMDXPCVOjQPe8j8+nOaya30bn4nuqQnEYdo=; h=Cc:Date:From:Reply-To:Subject:To; b=QO5lvhuIw1DDGERgAw+HmD3r94Kn3VIZdwnG51lY5lJ51/nllGJsfqYHnSDUDKGTfOD qE134yz8kPnPvQ/9B7i6r3XU7wkWY5fBUGrYzqiVekd/DOyrj23yrqRIp549WPIKJf5ab fyS0p3BJJzy3jZVWMac/5r4PRCcQZmB0uiw= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299408353100028 Content-Type: text/plain; charset="utf-8" Read the memory map information through the QemuFwCfg interface, then build the page table through the memory map information, and finally enable Mmu. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../LoongArchQemuPkg/Include/Library/MmuLib.h | 85 ++ .../LoongArchQemuPkg/Library/MmuLib/Mmu.S | 35 + .../Library/MmuLib/MmuBaseLib.inf | 35 + .../Library/MmuLib/MmuBaseLibPei.inf | 45 + .../Library/MmuLib/MmuLibCore.c | 908 ++++++++++++++++++ .../Library/MmuLib/MmuLibCore.h | 39 + .../Library/MmuLib/MmuLibCorePei.c | 236 +++++ .../LoongArchQemuPkg/Library/MmuLib/mmu.h | 104 ++ .../LoongArchQemuPkg/Library/MmuLib/page.h | 267 +++++ .../LoongArchQemuPkg/Library/MmuLib/pte.h | 57 ++ 10 files changed, 1811 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/MmuL= ib.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBa= seLib.inf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBa= seLibPei.inf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLi= bCore.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLi= bCore.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLi= bCorePei.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/mmu.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/pte.h diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/MmuLib.h b/= Platform/Loongson/LoongArchQemuPkg/Include/Library/MmuLib.h new file mode 100644 index 0000000000..6c501eca07 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/MmuLib.h @@ -0,0 +1,85 @@ +/** @file + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - EXC - execute +**/ +#ifndef MMU_LIB_H_ +#define MMU_LIB_H_ +/** + write operation is performed Count times from the first element of Buffe= r. +Convert EFI Attributes to Loongarch Attributes. + @param[in] EfiAttributes Efi Attributes. + + @retval LoongArch Attributes. +**/ +UINTN +EfiAttributeToLoongArchAttribute ( + IN UINTN EfiAttributes + ); + +/** + Finds the length and memory properties of the memory region correspondin= g to the specified base address. + + @param[in] BaseAddress To find the base address of the memory region. + @param[in] EndAddress To find the end address of the memory region. + @param[out] RegionLength The length of the memory region found. + @param[out] RegionAttributes Properties of the memory region found. + + @retval EFI_SUCCESS The corresponding memory area was successfully f= ound + EFI_NOT_FOUND No memory area found +**/ +EFI_STATUS +GetLoongArchMemoryRegion ( + IN UINTN BaseAddress, + IN UINTN EndAddress, + OUT UINTN *RegionLength, + OUT UINTN *RegionAttributes + ); + +/** + Sets the Attributes of the specified memory region + + @param[in] BaseAddress The base address of the memory region to set th= e Attributes. + @param[in] Length The length of the memory region to set the Attr= ibutes. + @param[in] Attributes The Attributes to be set. + + @retval EFI_SUCCESS The Attributes was set successfully + +**/ +EFI_STATUS +LoongArchSetMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN Length, + IN UINTN Attributes + ); + +/** + Sets the non-executable Attributes for the specified memory region + + @param[in] BaseAddress The base address of the memory region to set th= e Attributes. + @param[in] Length The length of the memory region to set the Attr= ibutes. + + @retval EFI_SUCCESS The Attributes was set successfully +**/ +EFI_STATUS +LoongArchSetMemoryRegionNoExec ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN Length + ); +/** + Create a page table and initialize the MMU. + + @param[] VOID + + @retval VOID +**/ +VOID +EFIAPI +ConfigureMmu ( + VOID + ); +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S b/Plat= form/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S new file mode 100644 index 0000000000..a697b54e65 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S @@ -0,0 +1,35 @@ +#-------------------------------------------------------------------------= ----- +# +# LoongArch for LoongArch +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#-------------------------------------------------------------------------= ---- + +#ifndef _KERNEL +#define _KERNEL +#endif + +#include "Library/Cpu.h" +#include "LoongArchAsmMacro.h" + +# Query the page table. +# +# @param VOID +# +# @retval VOID +ASM_FUNC(HandleTlbRefill) + csrwr T0, LOONGARCH_CSR_TLBRSAVE + csrrd T0, LOONGARCH_CSR_PGD + lddir T0, T0, 3 #Put pud BaseAddress into T0 + lddir T0, T0, 2 #Put pmd BaseAddress into T0 + lddir T0, T0, 1 #Put pte BaseAddress into T0 + ldpte T0, 0 + ldpte T0, 1 + tlbfill + csrrd T0, LOONGARCH_CSR_TLBRSAVE + ertn +.globl HandleTlbRefillEnd +HandleTlbRefillEnd: diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLib.i= nf b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLib.inf new file mode 100644 index 0000000000..d8cfe6776e --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLib.inf @@ -0,0 +1,35 @@ +## @file +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D MmuBaseLib + FILE_GUID =3D da8f0232-fb14-42f0-922c-63104d2c70be + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D MmuLib + + CONSTRUCTOR =3D MmuInitialize +[Sources.common] + MmuLibCore.c + +[Packages] + MdePkg/MdePkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + +[PCD] + gLoongArchQemuPkgTokenSpaceGuid.PcdSwapPageDir + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPgd + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPud + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPmd + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPte + +[LibraryClasses] + MemoryAllocationLib + PcdLib + DebugLib diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPe= i.inf b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPei.inf new file mode 100644 index 0000000000..20e50218af --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPei.inf @@ -0,0 +1,45 @@ +## @file +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D MmuPeiLib + FILE_GUID =3D da8f0232-fb14-42f0-922c-63104d2c70bd + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D MmuLib | SEC PEIM + +[Sources.common] + MmuLibCorePei.c + Mmu.S + MmuLibCore.h + MmuLibCore.c + +[Packages] + MdePkg/MdePkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + OvmfPkg/OvmfPkg.dec + +[PCD] + gLoongArchQemuPkgTokenSpaceGuid.PcdSwapPageDir + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPgd + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPud + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPmd + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPte + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase + gLoongArchQemuPkgTokenSpaceGuid.PcdRamSize + +[FixedPcd] + gLoongArchQemuPkgTokenSpaceGuid.PcdRamRegionsBottom + +[LibraryClasses] + MemoryAllocationLib + PcdLib + DebugLib + QemuFwCfgLib diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c= b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c new file mode 100644 index 0000000000..d737759ad2 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c @@ -0,0 +1,908 @@ +/** @file + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Pgd or Pgd or PGD - Page Global Directory + - Pud or Pud or PUD - Page Upper Directory + - Pmd or Pmd or PMD - Page Middle Directory + - Pte or pte or PTE - Page Table Entry + - Val or VAL or val - Value + - Dir - Directory +**/ +#include +#include +#include +#include +#include +#include "Library/Cpu.h" +#include "pte.h" +#include "page.h" +#include "mmu.h" + +BOOLEAN mMmuInited =3D FALSE; +/** + Check to see if mmu successfully initializes. + + @param VOID. + + @retval TRUE Initialization has been completed. + FALSE Initialization did not complete. +**/ +BOOLEAN +MmuIsInit (VOID) { + if ((mMmuInited =3D=3D TRUE) || + (PcdGet64 (PcdSwapPageDir) !=3D 0)) { + return TRUE; + } + return FALSE; +} + +/** + Iterates through the page directory to initialize it. + + @param Dst A pointer to the directory of the page to initialize. + @param Num The number of page directories to initialize. + @param Src A pointer to the data used to initialize the page directory. + + @retval VOID. +**/ +VOID +PageDirInit ( + IN VOID *Dst, + IN UINTN Num, + IN VOID *Src + ) +{ + UINTN *Ptr; + UINTN *End; + UINTN Entry; + + Entry =3D (UINTN)Src; + Ptr =3D (UINTN *)Dst; + End =3D Ptr + Num; + + for ( ;Ptr < End; Ptr++) { + *Ptr =3D Entry; + } + + return ; +} +/** + Gets the virtual address corresponding to the page global directory tabl= e entry. + + @param Address the virtual address for the table entry. + + @retval PGD A pointer to get the table item. +**/ +PGD * +PgdOffset ( + IN UINTN Address + ) +{ + return ((PGD *)PcdGet64 (PcdSwapPageDir)) + PGD_INDEX (Address); +} +/** + Gets the virtual address corresponding to the page upper directory table= entry. + + @param Pgd A pointer to a page global directory table entry. + @param Address the virtual address for the table entry. + + @retval PUD A pointer to get the table item. +**/ +PUD * +PudOffset ( + IN PGD *Pgd, + IN UINTN Address + ) +{ + UINTN PgdVal =3D (UINTN)PGD_VAL (*Pgd); + return (PUD *)PgdVal + PUD_INDEX (Address); +} +/** + Gets the virtual address corresponding to the page middle directory tabl= e entry. + + @param Pud A pointer to a page upper directory table entry. + @param Address the virtual address for the table entry. + + @retval PMD A pointer to get the table item. +**/ +PMD * +PmdOffset ( + IN PUD *Pud, + IN UINTN Address + ) +{ + UINTN PudVal =3D PUD_VAL (*Pud); + return (PMD *)PudVal + PMD_INDEX (Address); +} +/** + Gets the virtual address corresponding to the page table entry. + + @param Pmd A pointer to a page middle directory table entry. + @param Address the virtual address for the table entry. + + @retval PTE A pointer to get the table item. +**/ +PTE * +PteOffset ( + IN PMD *Pmd, + IN UINTN Address + ) +{ + UINTN PmdVal =3D (UINTN)PMD_VAL (*Pmd); + return (PTE *)PmdVal + PTE_INDEX (Address); +} + +/** + Sets the value of the page table entry. + + @param Pte A pointer to a page table entry. + @param PteVal The value of the page table entry to set. + + @retval VOID +**/ +VOID +SetPte ( + IN PTE *Pte, + IN PTE PteVal + ) +{ + *Pte =3D PteVal; +} +/** + Sets the value of the page global directory. + + @param Pgd A pointer to a page global directory. + @param Pud The value of the page global directory to set. + + @retval VOID +**/ +VOID +SetPgd ( + IN PGD *Pgd, + IN PUD *Pud + ) +{ + *Pgd =3D (PGD) {((UINTN)Pud)}; +} + +/** + Sets the value of the page upper directory. + + @param Pud A pointer to a page upper directory. + @param Pmd The value of the page upper directory to set. + + @retval VOID +**/ +VOID +SetPud ( + IN PUD *Pud, + IN PMD *Pmd + ) +{ + *Pud =3D (PUD) {((UINTN)Pmd)}; +} + +/** + Sets the value of the page middle directory. + + @param Pmd A pointer to a page middle directory. + @param Pte The value of the page middle directory to set. + + @retval VOID +**/ +VOID +SetPmd ( + IN PMD *Pmd, + IN PTE *Pte + ) +{ + *Pmd =3D (PMD) {((UINTN)Pte)}; +} +/** + Free up memory space occupied by page tables. + + @param Pte A pointer to the page table. + + @retval VOID +**/ +VOID +PteFree ( + IN PTE *Pte + ) +{ + FreePages ((VOID *)Pte, 1); +} +/** + Free up memory space occupied by page middle directory. + + @param Pmd A pointer to the page middle directory. + + @retval VOID +**/ +VOID +PmdFree ( + IN PMD *Pmd + ) +{ + FreePages ((VOID *)Pmd, 1); +} +/** + Free up memory space occupied by page upper directory. + + @param Pud A pointer to the page upper directory. + + @retval VOID +**/ +VOID +PudFree ( + IN PUD *Pud + ) +{ + FreePages ((VOID *)Pud, 1); +} +/** + Requests the memory space required for the page upper directory, + initializes it, and places it in the specified page global directory + + @param Pgd A pointer to the page global directory. + + @retval EFI_SUCCESS Memory request successful. + @retval EFI_OUT_OF_RESOURCES Resource exhaustion cannot be requested t= o memory. +**/ +INTN +PudAlloc ( + IN PGD *Pgd + ) +{ + PUD *Pud =3D (PUD *) AllocatePages (1); + if (!Pud) { + return EFI_OUT_OF_RESOURCES; + } + + PageDirInit ((VOID *)Pud, ENTRYS_PER_PUD, (VOID *)PcdGet64 (PcdInvalidPm= d)); + + if (pgd_none (*Pgd)) { + SetPgd (Pgd, Pud); + } else { /* Another has populated it */ + PudFree (Pud); + } + + return EFI_SUCCESS; +} +/** + Requests the memory space required for the page middle directory, + initializes it, and places it in the specified page upper directory + + @param Pud A pointer to the page upper directory. + + @retval EFI_SUCCESS Memory request successful. + @retval EFI_OUT_OF_RESOURCES Resource exhaustion cannot be requested t= o memory. +**/ +EFI_STATUS +PmdAlloc ( + IN PUD *Pud + ) +{ + PMD *Pmd; + + Pmd =3D (PMD *) AllocatePages (1); + if (!Pmd) { + return EFI_OUT_OF_RESOURCES; + } + + PageDirInit ((VOID *)Pmd, ENTRYS_PER_PMD, (VOID *)PcdGet64 (PcdInvalidPt= e)); + + if (pud_none (*Pud)) { + SetPud (Pud, Pmd); + } else {/* Another has populated it */ + PmdFree (Pmd); + } + + return EFI_SUCCESS; +} +/** + Requests the memory space required for the page table, + initializes it, and places it in the specified page middle directory + + @param Pmd A pointer to the page middle directory. + + @retval EFI_SUCCESS Memory request successful. + @retval EFI_OUT_OF_RESOURCES Resource exhaustion cannot be requested t= o memory. +**/ +INTN +PteAlloc ( + IN PMD *Pmd + ) +{ + PTE *Pte; + + Pte =3D (PTE *) AllocatePages (1); + if (!Pte) { + return EFI_OUT_OF_RESOURCES; + } + + Pte =3D ZeroMem (Pte, EFI_PAGE_SIZE); + + if (pmd_none (*Pmd)) { + SetPmd (Pmd, Pte); + } else { /* Another has populated it */ + PteFree (Pte); + } + + return EFI_SUCCESS; +} +/** + Requests the memory space required for the page upper directory, + initializes it, and places it in the specified page global directory, + and get the page upper directory entry corresponding to the virtual addr= ess + + @param Pgd A pointer to the page global directory. + + @retval Gets the page upper directory entry +**/ +PUD * +PudAllocGet ( + IN PGD *Pgd, + IN UINTN Address + ) +{ + return ((pgd_none (*(Pgd)) && PudAlloc (Pgd)) ? + NULL : PudOffset (Pgd, Address)); +} +/** + Requests the memory space required for the page middle directory, + initializes it, and places it in the specified page upper directory, + and get the page middle directory entry corresponding to the virtual add= ress + + @param Pud A pointer to the page upper directory. + + @retval Gets the page middle directory entry +**/ +PMD * +PmdAllocGet ( + IN PUD *Pud, + IN UINTN Address + ) +{ + PMD * ret =3D (pud_none (*Pud) && PmdAlloc (Pud))? + NULL: PmdOffset (Pud, Address); + DEBUG ((DEBUG_VERBOSE, "%a %d PudVal %p PmdOffset %p PMD_INDEX %p .\n", = __func__, __LINE__, + Pud->PudVal, PmdOffset (Pud, Address), PMD_INDEX (Address) )); + + return ret; +} +/** + Requests the memory space required for the page table, + initializes it, and places it in the specified page middle directory, + and get the page table entry corresponding to the virtual address + + @param Pmd A pointer to the page upper directory. + + @retval Gets the page table entry +**/ +PTE * +PteAllocGet ( + IN PMD *Pmd, + IN UINTN Address + ) +{ + return (pmd_none (*Pmd) && PteAlloc (Pmd))? + NULL: PteOffset (Pmd, Address); +} + /** + Convert page middle directory table entry to tlb entry. + + @param PmdVal page middle directory table entry value. + + @retval tlb entry value. + **/ +UINTN +PmdToTlbEntry ( + UINTN PmdVal + ) +{ + UINTN Value; + + Value =3D PmdVal ^ PAGE_HUGE; + Value |=3D ((Value & PAGE_HGLOBAL) >> + (PAGE_HGLOBAL_SHIFT - PAGE_GLOBAL_SHIFT)); + + return Value; +} + + /** + Update huge tlb. + + @param address The address corresponding to tlb. + @param Pte A pointer to the page table entry. + + @retval VOID. + **/ +VOID +UpdateHugeTlb ( + IN UINTN address, + PTE *Pte) +{ + INTN Idx; + UINTN TlbEntry; + address &=3D (PAGE_MASK << 1); + LOONGARCH_CSR_WRITEQ (address, LOONGARCH_CSR_TLBEHI); + LOONGARCH_TLB_SRCH(); + LOONGARCH_CSR_READQ (Idx, LOONGARCH_CSR_TLBIDX); + + if (Idx < 0) { + return ; + } + WRITE_CSR_PAGE_SIZE (HUGE_PAGE_SIZE); + TlbEntry =3D PmdToTlbEntry(PTE_VAL (*Pte)); + LOONGARCH_CSR_WRITEQ(TlbEntry, LOONGARCH_CSR_TLBELO0); + LOONGARCH_CSR_WRITEQ(TlbEntry + (HUGE_PAGE_SIZE >> 1), LOONGARCH_CSR_TLB= ELO1); + LOONGARCH_TLB_WR (); + + WRITE_CSR_PAGE_SIZE (DEFAULT_PAGE_SIZE); + + return ; +} + /** + Update tlb. + + @param address The address corresponding to tlb. + @param Pte A pointer to the page table entry. + + @retval VOID. + **/ +VOID +UpdateTlb ( + IN UINTN address, + PTE *Pte) +{ + INTN Idx; + if (IS_HUGE_PAGE (Pte->PteVal)) { + return UpdateHugeTlb(address, Pte); + } + + address &=3D (PAGE_MASK << 1); + LOONGARCH_CSR_WRITEQ (address, LOONGARCH_CSR_TLBEHI); + LOONGARCH_TLB_SRCH(); + LOONGARCH_CSR_READQ (Idx, LOONGARCH_CSR_TLBIDX); + + if (Idx < 0) { + return ; + } + + if ((UINTN)Pte & sizeof(PTE)) { + Pte--; + } + + WRITE_CSR_PAGE_SIZE (DEFAULT_PAGE_SIZE); + LOONGARCH_CSR_WRITEQ(PTE_VAL (*Pte), LOONGARCH_CSR_TLBELO0); + Pte++; + LOONGARCH_CSR_WRITEQ(PTE_VAL (*Pte), LOONGARCH_CSR_TLBELO1); + LOONGARCH_TLB_WR (); + + return ; +} + +/** + Gets the physical address of the page table entry corresponding to the s= pecified virtual address. + + @param Address the corresponding virtual address of the page table ent= ry. + + @retval A pointer to the page table entry. + @retval NULL +**/ +PTE * +GetPteAddress ( + IN UINTN Address + ) +{ + PGD *Pgd; + PUD *Pud; + PMD *Pmd; + + Pgd =3D PgdOffset (Address); + + if (pgd_none (*Pgd)) { + return NULL; + } + + Pud =3D PudOffset (Pgd, Address); + + if (pud_none (*Pud)) { + return NULL; + } + + Pmd =3D PmdOffset (Pud, Address); + if (pmd_none (*Pmd)) { + return NULL; + } + + if (IS_HUGE_PAGE (Pmd->PmdVal)) { + return ((PTE *)Pmd); + } + + return PteOffset (Pmd, Address); +} +/** + Establishes a page table entry based on the specified memory region. + + @param Pmd A pointer to the page middle directory. + @param Address The memory space start address. + @param End The end address of the memory space. + @param Attributes Memory space Attributes. + + @retval EFI_SUCCESS The page table entry was created successfully. + @retval EFI_OUT_OF_RESOURCES Page table entry establishment failed = due to resource exhaustion. +**/ +EFI_STATUS +MemoryMapPteRange ( + IN PMD *Pmd, + IN UINTN Address, + IN UINTN End, + IN UINTN Attributes + ) +{ + PTE *Pte; + PTE PteVal; + BOOLEAN UpDate; + + Pte =3D PteAllocGet (Pmd, Address); + if (!Pte) { + return EFI_OUT_OF_RESOURCES; + } + + do { + UpDate =3D FALSE; + PteVal =3D MAKE_PTE (Address, Attributes); + DEBUG ((DEBUG_VERBOSE, + "%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p PTE_IND= EX %p MAKE_PTE %p\n", + __func__, __LINE__, Address, PGD_INDEX (Address), PUD_INDEX (Addres= s), PMD_INDEX (Address), + PTE_INDEX (Address), PteVal)); + + if ((!pte_none (*Pte)) && + (PTE_VAL(*Pte) !=3D PTE_VAL(PteVal))) + { + UpDate =3D TRUE; + } + + SetPte (Pte, PteVal); + if (UpDate) { + UpdateTlb (Address, Pte); + } + } while (Pte++, Address +=3D EFI_PAGE_SIZE, Address !=3D End); + + return EFI_SUCCESS; +} +/** + Establishes a page middle directory based on the specified memory region. + + @param Pud A pointer to the page upper directory. + @param Address The memory space start address. + @param End The end address of the memory space. + @param Attributes Memory space Attributes. + + @retval EFI_SUCCESS The page middle directory was created successf= ully. + @retval EFI_OUT_OF_RESOURCES Page middle directory establishment fa= iled due to resource exhaustion. +**/ +EFI_STATUS +MemoryMapPmdRange ( + IN PUD *Pud, + IN UINTN Address, + IN UINTN End, + IN UINTN Attributes + ) +{ + PMD *Pmd; + PTE *Pte; + UINTN Next; + UINTN AddressStart_HugePage; + UINTN AddressEnd_HugePage; + + Pmd =3D PmdAllocGet (Pud, Address); + if (!Pmd) { + return EFI_OUT_OF_RESOURCES; + } + + do { + Next =3D PMD_ADDRESS_END (Address, End); + if (((Address & (~PMD_MASK)) =3D=3D 0) && + ((Next & (~PMD_MASK)) =3D=3D 0) && + (pmd_none (*Pmd))) + { + DEBUG ((DEBUG_VERBOSE, + "%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p MAKE_= HUGE_PTE %p\n", + __func__, __LINE__, Address, PGD_INDEX (Address), PUD_INDEX (Addr= ess), PMD_INDEX (Address), + MAKE_HUGE_PTE (Address, Attributes))); + + SetPmd (Pmd, (PTE *)MAKE_HUGE_PTE (Address, Attributes)); + } else { + if ((pmd_none (*Pmd)) || + ((!pmd_none (*Pmd)) && + (!IS_HUGE_PAGE (Pmd->PmdVal)))) + { + if (MemoryMapPteRange (Pmd, Address, Next, Attributes)) { + return EFI_OUT_OF_RESOURCES; + } + } else { + SetPmd (Pmd, (PTE *)PcdGet64 (PcdInvalidPte)); + AddressStart_HugePage =3D Address & PMD_MASK; + AddressEnd_HugePage =3D AddressStart_HugePage + HUGE_PAGE_SIZE; + if (MemoryMapPteRange (Pmd, AddressStart_HugePage, AddressEnd_Hug= ePage, Attributes)) { + return EFI_OUT_OF_RESOURCES; + } + Pte =3D GetPteAddress (AddressStart_HugePage); + if (Pte =3D=3D NULL) { + continue ; + } + UpdateTlb (AddressStart_HugePage, Pte); + if (AddressEnd_HugePage > End) { + Next =3D End; + } + } + } + } while (Pmd++, Address =3D Next, Address !=3D End); + + return 0; +} +/** + Establishes a page upper directory based on the specified memory region. + + @param Pgd A pointer to the page global directory. + @param Address The memory space start address. + @param End The end address of the memory space. + @param Attributes Memory space Attributes. + + @retval EFI_SUCCESS The page upper directory was created successfu= lly. + @retval EFI_OUT_OF_RESOURCES Page upper directory establishment fai= led due to resource exhaustion. +**/ +EFI_STATUS +MemoryMapPudRange ( + IN PGD *Pgd, + IN UINTN Address, + IN UINTN End, + IN UINTN Attributes + ) +{ + PUD *Pud; + UINTN Next; + + Pud =3D PudAllocGet (Pgd, Address); + if (!Pud) { + return EFI_OUT_OF_RESOURCES; + } + + do { + Next =3D PUD_ADDRESS_END (Address, End); + if (MemoryMapPmdRange (Pud, Address, Next, Attributes)) { + return EFI_OUT_OF_RESOURCES; + } + } while (Pud++, Address =3D Next, Address !=3D End); + return EFI_SUCCESS; +} +/** + Establishes a page global directory based on the specified memory region. + + @param Start The memory space start address. + @param End The end address of the memory space. + @param Attributes Memory space Attributes. + + @retval EFI_SUCCESS The page global directory was created successf= ully. + @retval EFI_OUT_OF_RESOURCES Page global directory establishment fa= iled due to resource exhaustion. +**/ +EFI_STATUS +MemoryMapPageRange ( + IN UINTN Start, + IN UINTN End, + IN UINTN Attributes + ) +{ + PGD *Pgd; + UINTN Next; + UINTN Address =3D Start; + EFI_STATUS Err; + + Pgd =3D PgdOffset (Address); + do { + Next =3D PGD_ADDRESS_END (Address, End); + Err =3D MemoryMapPudRange (Pgd, Address, Next, Attributes); + if (Err) { + return Err; + } + } while (Pgd++, Address =3D Next, Address !=3D End); + + return EFI_SUCCESS; +} + +/** + Page tables are established from memory-mapped tables. + + @param MemoryRegion A pointer to a memory-mapped table entry. + + @retval EFI_SUCCESS The page table was created successfully. + @retval EFI_OUT_OF_RESOURCES Page table establishment failed due t= o resource exhaustion. +**/ +EFI_STATUS +FillTranslationTable ( + IN MEMORY_REGION_DESCRIPTOR *MemoryRegion + ) +{ + return MemoryMapPageRange (MemoryRegion->VirtualBase, + (MemoryRegion->Length + MemoryRegion->VirtualBase), + MemoryRegion->Attributes); +} + +/** + write operation is performed Count times from the first element of Buffe= r. +Convert EFI Attributes to Loongarch Attributes. + @param[in] EfiAttributes Efi Attributes. + + @retval LoongArch Attributes. +**/ +UINTN +EfiAttributeToLoongArchAttribute ( + IN UINTN EfiAttributes + ) +{ + UINTN LoongArchAttributes =3D PAGE_VALID | PAGE_DIRTY | CACHE_CC | PAGE= _USER; + switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) { + case EFI_MEMORY_UC: + LoongArchAttributes |=3D CACHE_SUC; + break; + case EFI_MEMORY_WC: + case EFI_MEMORY_WT: + case EFI_MEMORY_WB: + LoongArchAttributes |=3D CACHE_CC; + break; + default : + LoongArchAttributes |=3D CACHE_CC; + break; + } + + // Write protection attributes + if ((EfiAttributes & EFI_MEMORY_RO) !=3D 0) { + LoongArchAttributes &=3D ~PAGE_DIRTY; + } + + //eXecute protection attribute + if ((EfiAttributes & EFI_MEMORY_XP) !=3D 0) { + LoongArchAttributes |=3D PAGE_NO_EXEC; + } + + return LoongArchAttributes; +} + +/** + Finds the length and memory properties of the memory region correspondin= g to the specified base address. + + @param[in] BaseAddress To find the base address of the memory region. + @param[in] EndAddress To find the end address of the memory region. + @param[out] RegionLength The length of the memory region found. + @param[out] RegionAttributes Properties of the memory region found. + + @retval EFI_SUCCESS The corresponding memory area was successfully f= ound + EFI_NOT_FOUND No memory area found +**/ +EFI_STATUS +GetLoongArchMemoryRegion ( + IN UINTN BaseAddress, + IN UINTN EndAddress, + OUT UINTN *RegionLength, + OUT UINTN *RegionAttributes + ) +{ + PTE *Pte; + UINTN Attributes; + UINTN AttributesTmp; + UINTN MaxAddress; + MaxAddress =3D LShiftU64 (1ULL, MAX_VA_BITS) - 1; + Pte =3D GetPteAddress (BaseAddress); + + if (!MmuIsInit ()) { + return EFI_SUCCESS; + } + if (Pte =3D=3D NULL) { + return EFI_NOT_FOUND; + } + Attributes =3D GET_PAGE_ATTRIBUTES (*Pte); + if (IS_HUGE_PAGE (Pte->PteVal)) { + *RegionAttributes =3D Attributes & (~(PAGE_HUGE)); + *RegionLength +=3D HUGE_PAGE_SIZE; + } else { + *RegionLength +=3D EFI_PAGE_SIZE; + *RegionAttributes =3D Attributes; + } + + while (BaseAddress <=3D MaxAddress) { + Pte =3D GetPteAddress (BaseAddress); + if (Pte =3D=3D NULL) { + return EFI_SUCCESS; + } + AttributesTmp =3D GET_PAGE_ATTRIBUTES (*Pte); + if (IS_HUGE_PAGE (Pte->PteVal)) { + if (AttributesTmp =3D=3D Attributes) { + *RegionLength +=3D HUGE_PAGE_SIZE; + } + BaseAddress +=3D HUGE_PAGE_SIZE; + } else { + if (AttributesTmp =3D=3D Attributes) { + *RegionLength +=3D EFI_PAGE_SIZE; + } + BaseAddress +=3D EFI_PAGE_SIZE; + } + + if (BaseAddress > EndAddress) { + break; + } + } + return EFI_SUCCESS; +} + +/** + Sets the Attributes of the specified memory region + + @param[in] BaseAddress The base address of the memory region to set th= e Attributes. + @param[in] Length The length of the memory region to set the Attr= ibutes. + @param[in] Attributes The Attributes to be set. + + @retval EFI_SUCCESS The Attributes was set successfully + +**/ +EFI_STATUS +LoongArchSetMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN Length, + IN UINTN Attributes + ) +{ + + if (!MmuIsInit ()) { + return EFI_SUCCESS; + } + Attributes =3D EfiAttributeToLoongArchAttribute (Attributes); + DEBUG ((DEBUG_VERBOSE, "%a %d %p %p %p.\n", __func__, __LINE__, BaseAddr= ess , Length, Attributes)); + MemoryMapPageRange (BaseAddress, BaseAddress + Length, Attributes); + + return EFI_SUCCESS; +} + +/** + Sets the non-executable Attributes for the specified memory region + + @param[in] BaseAddress The base address of the memory region to set th= e Attributes. + @param[in] Length The length of the memory region to set the Attr= ibutes. + + @retval EFI_SUCCESS The Attributes was set successfully +**/ +EFI_STATUS +LoongArchSetMemoryRegionNoExec ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN Length + ) +{ + if (MmuIsInit ()) { + Length =3D EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Length)); + LoongArchSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_XP); + } + return EFI_SUCCESS; +} + +/** + Check to see if mmu successfully initializes and saves the result. + + @param VOID. + + @retval EFI_SUCCESS Initialization succeeded. +**/ +EFI_STATUS +MmuInitialize (VOID) +{ + if (PcdGet64 (PcdSwapPageDir) !=3D 0) { + mMmuInited =3D TRUE; + } + + return EFI_SUCCESS; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h= b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h new file mode 100644 index 0000000000..e9f294b356 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h @@ -0,0 +1,39 @@ +/** @file + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Dir - Directory +**/ +#ifndef MMU_LIB_CORE_H_ +#define MMU_LIB_CORE_H_ +/** + Iterates through the page directory to initialize it. + + @param Dst A pointer to the directory of the page to initialize. + @param Num The number of page directories to initialize. + @param Src A pointer to the data used to initialize the page directory. + + @retval VOID. +**/ +VOID +PageDirInit ( + IN VOID *dest, + IN UINTN Count, + IN VOID *src + ); +/** + Page tables are established from memory-mapped tables. + + @param MemoryRegion A pointer to a memory-mapped table entry. + + @retval EFI_SUCCESS The page table was created successfully. + @retval EFI_OUT_OF_RESOURCES Page table establishment failed due t= o resource exhaustion. +**/ +EFI_STATUS +FillTranslationTable ( + IN MEMORY_REGION_DESCRIPTOR *MemoryRegion + ); +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePe= i.c b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePei.c new file mode 100644 index 0000000000..899f40fd94 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePei.c @@ -0,0 +1,236 @@ +/** @file + Platform PEI driver + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - FwCfg - Firmeware Config + - Tlb - Translation Lookaside Buffer +**/ +#include +#include +#include +#include +#include +#include "Library/Cpu.h" +#include "pte.h" +#include "page.h" +#include "mmu.h" +#include +#include "MmuLibCore.h" + +/** + Return the Virtual Memory Map of your platform + + This Virtual Memory Map is used by MemoryInitPei Module to initialize th= e MMU + on your platform. + + @param[out] VirtualMemoryMap Array of MEMORY_REGION_DESCRIPTOR + describing a Physical-to-Virtual Memory + mapping. This array must be ended by a + zero-filled entry. The allocated memory + will not be freed. + +**/ +VOID +GetMemoryMapFromFwCfg ( + OUT MEMORY_REGION_DESCRIPTOR **VirtualMemoryMap + ) +{ + + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + LOONGARCH_MEMMAP_ENTRY MemoryMapEntry; + LOONGARCH_MEMMAP_ENTRY *StartEntry; + LOONGARCH_MEMMAP_ENTRY *pEntry; + UINTN Processed; + MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable; + UINTN Index =3D 0; + ASSERT (VirtualMemoryMap !=3D NULL); + + VirtualMemoryTable =3D AllocatePool ( + sizeof (MEMORY_REGION_DESCRIPTOR) * + MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS + ); + VirtualMemoryTable[Index].PhysicalBase =3D 0x10000000; + VirtualMemoryTable[Index].VirtualBase =3D VirtualMemoryTable[Index].Phy= sicalBase; + VirtualMemoryTable[Index].Length =3D 0x80000000; + VirtualMemoryTable[Index].Attributes =3D PAGE_VALID | PAGE_USER | CAC= HE_CC | PAGE_DIRTY; + ++Index; + + Status =3D QemuFwCfgFindFile ("etc/memmap", &FwCfgItem, &FwCfgSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a %d read etc/memmap error Status %d \n", __fun= c__, __LINE__, Status)); + ZeroMem (&VirtualMemoryTable[Index], sizeof (MEMORY_REGION_DESCRIPTOR)= ); + *VirtualMemoryMap =3D VirtualMemoryTable; + return ; + } + if (FwCfgSize % sizeof MemoryMapEntry !=3D 0) { + DEBUG ((DEBUG_ERROR, "no MemoryMapEntry FwCfgSize:%d\n", FwCfgSize)); + } + + QemuFwCfgSelectItem (FwCfgItem); + StartEntry =3D AllocatePages (EFI_SIZE_TO_PAGES (FwCfgSize)); + QemuFwCfgReadBytes (FwCfgSize, StartEntry); + for (Processed =3D 0; Processed < (FwCfgSize / sizeof MemoryMapEntry); P= rocessed++) { + pEntry =3D StartEntry + Processed; + if (pEntry->Length =3D=3D 0) { + continue; + } + + DEBUG ((DEBUG_INFO, "MemmapEntry Base %p length %p type %d\n", pEntry= ->BaseAddr, pEntry->Length, pEntry->Type)); + VirtualMemoryTable[Index].PhysicalBase =3D pEntry->BaseAddr; + VirtualMemoryTable[Index].VirtualBase =3D VirtualMemoryTable[Index].P= hysicalBase; + VirtualMemoryTable[Index].Length =3D pEntry->Length; + VirtualMemoryTable[Index].Attributes =3D PAGE_VALID | PAGE_USER | C= ACHE_CC | PAGE_DIRTY; + ++Index; + } + + FreePages (StartEntry, EFI_SIZE_TO_PAGES (FwCfgSize)); + // End of Table + ZeroMem (&VirtualMemoryTable[Index], sizeof (MEMORY_REGION_DESCRIPTOR)); + *VirtualMemoryMap =3D VirtualMemoryTable; + return ; +} + +/** + Create a page table and initialize the MMU. + + @param[] VOID + + @retval VOID +**/ +EFIAPI +VOID +ConfigureMmu (VOID) +{ + PGD *SwapperPageDir =3D NULL; + PGD *InvalidPgd =3D NULL; + PUD *InvalidPudTable =3D NULL; + PMD *InvalidPmdTable =3D NULL; + PTE *InvalidPteTable =3D NULL; + MEMORY_REGION_DESCRIPTOR *MemoryTable =3D NULL; + RETURN_STATUS PcdStatus; + UINTN PgdShift =3D PGD_SHIFT; + UINTN PgdWide =3D PGD_WIDE; + UINTN PudShift =3D PUD_SHIFT; + UINTN PudWide =3D PUD_WIDE; + UINTN PmdShift =3D PMD_SHIFT; + UINTN PmdWide =3D PMD_WIDE; + UINTN PteShift =3D PTE_SHIFT; + UINTN PteWide =3D PTE_WIDE; + UINTN PageEnable =3D 1 << 4; + VOID *TlbReEntry; + UINTN PageSize; + + SwapperPageDir =3D AllocatePages (EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE)); + InvalidPgd =3D AllocatePages (EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE)); + InvalidPudTable =3D AllocatePages (EFI_SIZE_TO_PAGES (PUD_TABLE_SIZE)); + InvalidPmdTable =3D AllocatePages (EFI_SIZE_TO_PAGES (PMD_TABLE_SIZE)); + InvalidPteTable =3D AllocatePages (EFI_SIZE_TO_PAGES (PTE_TABLE_SIZE)); + ZeroMem (InvalidPteTable, PTE_TABLE_SIZE); + + if ((!InvalidPgd) || + (!InvalidPudTable) || + (!InvalidPmdTable) || + (!InvalidPteTable)) + { + goto FreeTranslationTable; + } + + /*pgd init*/ + PageDirInit (SwapperPageDir , ENTRYS_PER_PGD, InvalidPudTable); + /*pgd init*/ + PageDirInit (InvalidPgd, ENTRYS_PER_PGD, InvalidPudTable); + /*pud init*/ + PageDirInit (InvalidPudTable, ENTRYS_PER_PUD, InvalidPmdTable); + /*pmd init*/ + PageDirInit (InvalidPmdTable, ENTRYS_PER_PMD, InvalidPteTable); + GetMemoryMapFromFwCfg (&MemoryTable); + + PcdStatus |=3D PcdSet64S (PcdSwapPageDir, (UINTN)SwapperPageDir); + PcdStatus |=3D PcdSet64S (PcdInvalidPgd, (UINTN)InvalidPgd); + PcdStatus |=3D PcdSet64S (PcdInvalidPud, (UINTN)InvalidPudTable); + PcdStatus |=3D PcdSet64S (PcdInvalidPmd, (UINTN)InvalidPmdTable); + PcdStatus |=3D PcdSet64S (PcdInvalidPte, (UINTN)InvalidPteTable); + ASSERT_RETURN_ERROR (PcdStatus); + + while (MemoryTable->Length !=3D 0) { + DEBUG ((DEBUG_VERBOSE, "%a %d VirtualBase %p VirtualEnd %p Attributes = %p .\n", __func__, __LINE__, + MemoryTable->VirtualBase, + (MemoryTable->Length + MemoryTable->VirtualBase), + MemoryTable->Attributes)); + + PcdStatus =3D FillTranslationTable (MemoryTable); + if (EFI_ERROR (PcdStatus)) { + goto FreeTranslationTable; + } + MemoryTable++; + } + + /*set page size*/ + WRITE_CSR_PAGE_SIZE (DEFAULT_PAGE_SIZE); + WRITE_CSR_STLB_PAGE_SIZE (DEFAULT_PAGE_SIZE); + WRITE_CSR_TLBREFILL_PAGE_SIZE (DEFAULT_PAGE_SIZE); + READ_CSR_PAGE_SIZE (PageSize); + if (PageSize !=3D DEFAULT_PAGE_SIZE) { + goto FreeTranslationTable; + } + + TlbReEntry =3D AllocatePages (1); + if (TlbReEntry =3D=3D NULL) { + goto FreeTranslationTable; + } + CopyMem ((char *)TlbReEntry, HandleTlbRefill, (HandleTlbRefillEnd - Hand= leTlbRefill)); + SET_REFILL_TLBBASE ((UINTN)HandleTlbRefill); + + DEBUG ((DEBUG_VERBOSE, + "%a %d PteShift %d PteWide %d PmdShift %d PmdWide %d PudShift %d PudW= ide %d PgdShift %d PgdWide %d.\n", + __func__, __LINE__, + PteShift, PteWide, PmdShift, PmdWide,PudShift, PudWide, PgdShift, PgdW= ide)); + + LOONGARCH_CSR_WRITEQ (PteShift | PteWide << 5 | PmdShift << 10 | PmdWide= << 15 | PudShift << 20 | PudWide << 25, + LOONGARCH_CSR_PWCTL0); + LOONGARCH_CSR_WRITEQ (PgdShift | PgdWide << 6, LOONGARCH_CSR_PWCTL1); + LOONGARCH_CSR_WRITEQ ((UINTN)SwapperPageDir, LOONGARCH_CSR_PGDL); + LOONGARCH_CSR_WRITEQ ((UINTN)InvalidPgd, LOONGARCH_CSR_PGDH); + + DEBUG ((DEBUG_INFO, "%a %d Enable Mmu Start PageBassAddress %p.\n", __fu= nc__, __LINE__, SwapperPageDir)); + LOONGARCH_CSR_XCHGQ ( PageEnable, 1 << 4, LOONGARCH_CSR_CRMD); + DEBUG ((DEBUG_INFO, "%a %d Enable Mmu End.\n", __func__, __LINE__)); + + return ; + +FreeTranslationTable: + if (SwapperPageDir) { + FreePages (SwapperPageDir, EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE)); + } + + if (InvalidPgd) { + FreePages (InvalidPgd, EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE)); + } + + if (InvalidPudTable) { + FreePages (InvalidPudTable, EFI_SIZE_TO_PAGES (PUD_TABLE_SIZE)); + } + + if (InvalidPmdTable) { + FreePages (InvalidPmdTable, EFI_SIZE_TO_PAGES (PMD_TABLE_SIZE)); + } + + if (InvalidPteTable) { + FreePages (InvalidPteTable, EFI_SIZE_TO_PAGES (PTE_TABLE_SIZE)); + } + + PcdSet64S (PcdSwapPageDir, (UINTN)0); + PcdSet64S (PcdInvalidPgd, (UINTN)0); + PcdSet64S (PcdInvalidPud, (UINTN)0); + PcdSet64S (PcdInvalidPmd, (UINTN)0); + PcdSet64S (PcdInvalidPte, (UINTN)0); + + return ; +} + diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/mmu.h b/Plat= form/Loongson/LoongArchQemuPkg/Library/MmuLib/mmu.h new file mode 100644 index 0000000000..50b785bb6e --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/mmu.h @@ -0,0 +1,104 @@ +/** @file + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Tlb or TLB - Translation Lookaside Buffer + - CSR - Cpu State Register + - PGDL - Page Global Directory Low + - PGDH - Page Global Directory High + - TLBIDX - TLB Index + - TLBREHI - TLB Refill Entry High + - PWCTL - Page Walk Control + - STLB - Singular Page Size TLB + - PS - Page Size +**/ +#ifndef MMU_H_ +#define MMU_H_ +/*page size 4k*/ +#define DEFAULT_PAGE_SIZE 0x0c +#define LOONGARCH_CSR_PGDL 0x19 /* Page table base address when VA[= 47] =3D 0 */ +#define LOONGARCH_CSR_PGDH 0x1a /* Page table base address when VA[= 47] =3D 1 */ +#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize, NP */ +#define LOONGARCH_CSR_TLBEHI 0x11 /* TLB EntryHi */ +#define LOONGARCH_CSR_TLBELO0 0x12 /* TLB EntryLo0 */ +#define LOONGARCH_CSR_TLBELO1 0x13 /* TLB EntryLo1 */ +#define LOONGARCH_CSR_TLBREHI 0x8e /* TLB refill entryhi */ +#define LOONGARCH_CSR_PWCTL0 0x1c /* PWCtl0 */ +#define LOONGARCH_CSR_PWCTL1 0x1d /* PWCtl1 */ +#define LOONGARCH_CSR_STLBPGSIZE 0x1e +#define CSR_TLBIDX_SIZE_MASK 0x3f000000 +#define CSR_TLBIDX_PS_SHIFT 24 +#define CSR_TLBIDX_SIZE CSR_TLBIDX_PS_SHIFT + +/* + Set Cpu Status Register STLB Page Size. + + @param val Page Size. + + @retval VOID + */ +#define WRITE_CSR_STLB_PAGE_SIZE(val) LOONGARCH_CSR_WRITEQ((val), LOONGAR= CH_CSR_STLBPGSIZE) +/* + Set Cpu Status Register Page Size. + + @param size Page Size. + + @retval VOID + */ +#define WRITE_CSR_PAGE_SIZE(size) LOONGARCH_CSR_XCHGQ((size) << CSR_TLBID= X_SIZE, CSR_TLBIDX_SIZE_MASK, LOONGARCH_CSR_TLBIDX) +/* + Set Cpu Status Register TLBREFILL Page Size. + + @param size Page Size. + + @retval VOID + */ +#define WRITE_CSR_TLBREFILL_PAGE_SIZE(size) LOONGARCH_CSR_XCHGQ((size) <<= CSR_TLBREHI_PS_SHIFT, CSR_TLBREHI_PS, LOONGARCH_CSR_TLBREHI) +/* + Set Cpu Status Register TLBREFILL Base Address. + + @param BaseAddress the code base address of TLB refills . + + @retval VOID + */ +#define SET_REFILL_TLBBASE(BaseAddress) LOONGARCH_CSR_WRITEQ((BaseAddress)= , LOONGARCH_CSR_TLBREBASE); +/* + Get Cpu Status Register Page Size. + + @param val Gets the page size. + + @retval VOID + */ +#define READ_CSR_PAGE_SIZE(val) \ +{ \ + LOONGARCH_CSR_READQ ((val), LOONGARCH_CSR_TLBIDX); \ + (val) =3D ((val) & CSR_TLBIDX_SIZE_MASK) >> CSR_TLBIDX_SIZE; \ +} + + +#define CSR_TLBREHI_PS_SHIFT 0 +#define CSR_TLBREHI_PS ((UINTN)(0x3f) << CSR_TLBREHI_PS_SHIFT) + +#define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | \ + EFI_MEMORY_WC | \ + EFI_MEMORY_WT | \ + EFI_MEMORY_WB | \ + EFI_MEMORY_UCE \ + ) + + +typedef struct { + EFI_PHYSICAL_ADDRESS PhysicalBase; + EFI_VIRTUAL_ADDRESS VirtualBase; + UINTN Length; + UINTN Attributes; +} MEMORY_REGION_DESCRIPTOR; + +// The total number of descriptors, including the final "end-of-table" des= criptor. +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS (128) + +extern CHAR8 HandleTlbRefill[], HandleTlbRefillEnd[]; +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h b/Pla= tform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h new file mode 100644 index 0000000000..3b3b0b72c3 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h @@ -0,0 +1,267 @@ +/** @file + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Pgd or Pgd or PGD - Page Global Directory + - Pud or Pud or PUD - Page Upper Directory + - Pmd or Pmd or PMD - Page Middle Directory + - Pte or pte or PTE - Page Table Entry + - Val or VAL or val - Value + - Dir - Directory +**/ +#ifndef PAGE_H_ +#define PAGE_H_ + +#define MAX_VA_BITS 47 +#define PGD_WIDE (8) +#define PUD_WIDE (9) +#define PMD_WIDE (9) +#define PTE_WIDE (9) + +#define ENTRYS_PER_PGD (1 << PGD_WIDE) +#define ENTRYS_PER_PUD (1 << PUD_WIDE) +#define ENTRYS_PER_PMD (1 << PMD_WIDE) +#define ENTRYS_PER_PTE (1 << PTE_WIDE) + +#define PGD_SHIFT (PUD_SHIFT + PUD_WIDE) +#define PUD_SHIFT (PMD_SHIFT + PMD_WIDE) +#define PMD_SHIFT (EFI_PAGE_SHIFT + PTE_WIDE) +#define PTE_SHIFT (EFI_PAGE_SHIFT) + +#define PGD_SIZE (1UL << PGD_SHIFT) +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PMD_SIZE (1UL << PMD_SHIFT) + +#define PGD_MASK (~(PGD_SIZE-1)) +#define PUD_MASK (~(PUD_SIZE-1)) +#define PMD_MASK (~(PMD_SIZE-1)) +#define PAGE_MASK (~(EFI_PAGE_SIZE - 1)) +#define PFN_MASK (~(((UINTN)(1) << (EFI_PAGE_SH= IFT)) - 1) & \ + (((UINTN)(1) << (PAGE_PFN_END= _SHIFT)) - 1)) + +typedef struct { UINTN PgdVal; } PGD; +typedef struct { UINTN PudVal; } PUD; +typedef struct { UINTN PmdVal; } PMD; +typedef struct { UINTN PteVal; } PTE; +/** + Gets the value of the page global directory table entry. + + @param x Page global directory struct variables. + + @retval the value of the page global directory table entry. + **/ +#define PGD_VAL(x) ((x).PgdVal) +/** + Gets the value of the page upper directory table entry. + + @param x Page upper directory struct variables. + + @retval the value of the page upper directory table entry. + **/ +#define PUD_VAL(x) ((x).PudVal) +/** + Gets the value of the page middle directory table entry. + + @param x Page middle directory struct variables. + + @retval the value of the page middle directory table entry. + **/ +#define PMD_VAL(x) ((x).PmdVal) +/** + Gets the value of the page table entry. + + @param x Page table entry struct variables. + + @retval the value of the page table entry. + **/ +#define PTE_VAL(x) ((x).PteVal) + + +#define PGD_TABLE_SIZE (ENTRYS_PER_PGD * sizeof(PGD)) +#define PUD_TABLE_SIZE (ENTRYS_PER_PUD * sizeof(PUD)) +#define PMD_TABLE_SIZE (ENTRYS_PER_PMD * sizeof(PMD)) +#define PTE_TABLE_SIZE (ENTRYS_PER_PTE * sizeof(PTE)) +/** + Gets the physical address of the record in the page table entry. + + @param x Page table entry struct variables. + + @retval the value of the physical address. + **/ +#define GET_PAGE_ATTRIBUTES(x) (UINTN) {(PTE_VAL(x) & ~PFN_MA= SK)} +/** + Gets the virtual address of the next block of the specified virtual addr= ess + that is aligned with the size of the global page directory mapping. + + @param Address Specifies the virtual address. + @param End The end address of the memory region. + + @retval the specified virtual address of the next block. + **/ +#define PGD_ADDRESS_END(Address, End) \ +({ UINTN Boundary =3D ((Address) + PGD_SIZE) & PGD_MASK; \ + (Boundary - 1 < (End) - 1)? Boundary: (End); \ +}) +/** + Gets the virtual address of the next block of the specified virtual addr= ess + that is aligned with the size of the page upper directory mapping. + + @param Address Specifies the virtual address. + @param End The end address of the memory region. + + @retval the specified virtual address of the next block. + **/ +#define PUD_ADDRESS_END(Address, End) \ +({ UINTN Boundary =3D ((Address) + PUD_SIZE) & PUD_MASK; \ + (Boundary - 1 < (End) - 1)? Boundary: (End); \ +}) +/** + Gets the virtual address of the next block of the specified virtual addr= ess + that is aligned with the size of the page middle directory mapping. + + @param Address Specifies the virtual address. + @param End The end address of the memory region. + + @retval the specified virtual address of the next block. + **/ +#define PMD_ADDRESS_END(Address, End) \ +({ UINTN Boundary =3D ((Address) + PMD_SIZE) & PMD_MASK; \ + (Boundary - 1 < (End) - 1)? Boundary: (End); \ +}) +/** + Get Specifies the virtual address corresponding to the index of the page= global directory table entry. + + @param Address Specifies the virtual address. + + @retval the index of the page global directory table entry. + **/ +#define PGD_INDEX(Address) (((Address) >> PGD_SHIFT) & (E= NTRYS_PER_PGD-1)) +/** + Get Specifies the virtual address corresponding to the index of the page= upper directory table entry. + + @param Address Specifies the virtual address. + @param End The end address of the memory region. + + @retval the index of the page upper directory table entry. + **/ +#define PUD_INDEX(Address) (((Address) >> PUD_SHIFT) & (E= NTRYS_PER_PUD - 1)) +/** + Get Specifies the virtual address corresponding to the index of the page= middle directory table entry. + + @param Address Specifies the virtual address. + + @retval the index of the page middle directory table entry. + **/ +#define PMD_INDEX(Address) (((Address) >> PMD_SHIFT) & (E= NTRYS_PER_PMD - 1)) +/** + Get Specifies the virtual address corresponding to the index of the page= table entry. + + @param Address Specifies the virtual address. + + @retval the index of the page table entry. + **/ +#define PTE_INDEX(Address) (((Address) >> EFI_PAGE_SHIFT)= & (ENTRYS_PER_PTE - 1)) + +/** + Calculates the value of the page table entry based on the specified virt= ual address and properties. + + @param Address Specifies the virtual address. + @param Attributes Specifies the Attributes. + + @retval the value of the page table entry. + **/ +#define MAKE_PTE(Address, Attributes) (PTE){((((Address) >> EFI_PAGE= _SHIFT) << 12) | (Attributes))} +/** + Calculates the value of the Huge page table entry based on the specified= virtual address and properties. + + @param Address Specifies the virtual address. + @param Attributes Specifies the Attributes. + + @retval the value of the HUGE page table entry. + **/ +#define MAKE_HUGE_PTE(Address, Attributes) (((((Address) >> PMD_SHIFT) <<= PMD_SHIFT) | ((Attributes) | PAGE_HUGE))) + /** + Check whether the large page table entry is. + + @param Val The value of the page table entry. + + @retval 1 Is huge page table entry. + @retval 0 Isn't huge page table entry. + **/ +#define IS_HUGE_PAGE(Val) (((Val) & PAGE_HUGE) =3D=3D PA= GE_HUGE) +#define HUGE_PAGE_SIZE (PMD_SIZE) + + /** + Check that the global page directory table entry is empty. + + @param pgd the global page directory struct variables. + + @retval 1 Is huge page table entry. + @retval 0 Isn't huge page table entry. + **/ +STATIC +inline +UINTN +pgd_none ( + IN PGD pgd + ) +{ + return (PGD_VAL(pgd) =3D=3D (UINTN)PcdGet64(PcdInvalidPud)); +} + + /** + Check that the page upper directory table entry is empty. + + @param pud Page upper directory struct variables. + + @retval 1 Is huge page table entry. + @retval 0 Isn't huge page table entry. + **/ +STATIC +inline +UINTN +pud_none ( + IN PUD pud + ) +{ + return (PUD_VAL(pud) =3D=3D (UINTN)PcdGet64 (PcdInvalidPmd)); +} + + /** + Check that the page middle directory table entry is empty. + + @param pmd Page middle directory struct variables. + + @retval 1 Is huge page table entry. + @retval 0 Isn't huge page table entry. + **/ +STATIC +inline +UINTN +pmd_none ( + IN PMD pmd + ) +{ + return (PMD_VAL(pmd) =3D=3D (UINTN)PcdGet64(PcdInvalidPte)); +} + /** + Check that the page table entry is empty. + + @param pmd Page table entry struct variables. + + @retval 1 Is huge page table entry. + @retval 0 Isn't huge page table entry. + **/ +STATIC +inline +UINTN +pte_none ( + IN PTE pte + ) +{ + return (!(PTE_VAL(pte) & (~PAGE_GLOBAL))); +} +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/pte.h b/Plat= form/Loongson/LoongArchQemuPkg/Library/MmuLib/pte.h new file mode 100644 index 0000000000..d6ac74f9c9 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/pte.h @@ -0,0 +1,57 @@ +/** @file + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Tlb or TLB - Translation Lookaside Buffer + - HGLOBAL - Huge Global + - PFN - Page Frame number + - EXEC - Execute + - PLV - Privilege Level + - RPLV - Restricted Privilege Level + - SUC - Strong-ordered UnCached + - CC - Coherent Cached + - WUC - Weak-ordered UnCached +**/ +#ifndef PTE_H_ +#define PTE_H_ +/*Page table property definitions */ +#define PAGE_VALID_SHIFT 0 +#define PAGE_DIRTY_SHIFT 1 +#define PAGE_PLV_SHIFT 2 /* 2~3, two bits */ +#define CACHE_SHIFT 4 /* 4~5, two bits */ +#define PAGE_GLOBAL_SHIFT 6 +#define PAGE_HUGE_SHIFT 6 /* HUGE is a PMD bit */ + +#define PAGE_HGLOBAL_SHIFT 12 /* HGlobal is a PMD bit */ +#define PAGE_PFN_SHIFT 12 +#define PAGE_PFN_END_SHIFT 48 +#define PAGE_NO_READ_SHIFT 61 +#define PAGE_NO_EXEC_SHIFT 62 +#define PAGE_RPLV_SHIFT 63 + +/* Used by TLB hardware (placed in EntryLo*) */ +#define PAGE_VALID ((UINTN)(1) << PAGE_VALID_SHIFT) +#define PAGE_DIRTY ((UINTN)(1) << PAGE_DIRTY_SHIFT) +#define PAGE_PLV ((UINTN)(3) << PAGE_PLV_SHIFT) +#define PAGE_GLOBAL ((UINTN)(1) << PAGE_GLOBAL_SHIFT) +#define PAGE_HUGE ((UINTN)(1) << PAGE_HUGE_SHIFT) +#define PAGE_HGLOBAL ((UINTN)(1) << PAGE_HGLOBAL_SHIFT) +#define PAGE_NO_READ ((UINTN)(1) << PAGE_NO_READ_SHIFT) +#define PAGE_NO_EXEC ((UINTN)(1) << PAGE_NO_EXEC_SHIFT) +#define PAGE_RPLV ((UINTN)(1) << PAGE_RPLV_SHIFT) +#define CACHE_MASK ((UINTN)(3) << CACHE_SHIFT) +#define PFN_SHIFT (EFI_PAGE_SHIFT - 12 + PAGE_PFN_SHIFT) + +#define PLV_KERNEL 0 +#define PLV_USER 3 + +#define PAGE_USER (PLV_USER << PAGE_PLV_SHIFT) +#define PAGE_KERNEL (PLV_KERN << PAGE_PLV_SHIFT) + +#define CACHE_SUC (0 << CACHE_SHIFT) /* Strong-ordered UnCached= */ +#define CACHE_CC (1 << CACHE_SHIFT) /* Coherent Cached */ +#define CACHE_WUC (2 << CACHE_SHIFT) /* Weak-ordered UnCached */ +#endif --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93894): https://edk2.groups.io/g/devel/message/93894 Mute This Topic: https://groups.io/mt/93715813/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93897+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93897+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299410; cv=none; d=zohomail.com; s=zohoarc; b=Eq0PjrjFsVK8E7y5SpBMVFtgGlLdJGnZzWVXhvEOwyhImH2px/Z37uhNMCJGt6xvdy+/mr1IPMay21ehM9QSOLLN2ErV6XcTXH8ASGkyBMFgx33KU4kOmUQKatwGtYsBsCPvyIbz/20HkvUK6+dGUIMZIne10m/5rLrw17PZLLg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299410; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=Hpc2lueSCJ5u/ZTpBBOdX3FHD5rO0X8Ms0gwg+F0CXM=; b=ZOesPzCv4xmaWM8ZNBlrfv7xxmTXY+fp85uhn3AOgxzjISfVLfvA4jqdkVuo05KE/33GmG80jiN3tH7fkF/IeZa50EgGUrxFTql8HYTZpwUE3UDBkNZu/e92Ju9dptbWG+6jJHmlj4IjJFWYxKLHjDOql6VTMKWg4rx5KQerg1U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93897+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299410142969.3953684194605; Thu, 15 Sep 2022 20:36:50 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id mdR8YY1788612x0vI8EESMAL; Thu, 15 Sep 2022 20:36:49 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web11.2176.1663299404600477085 for ; Thu, 15 Sep 2022 20:36:49 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S8; Fri, 16 Sep 2022 11:36:38 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 06/16] Platform/Loongson: Add StableTimerLib. Date: Fri, 16 Sep 2022 11:36:23 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S8 X-Coremail-Antispam: 1UD129KBjvJXoW3WryDur1fWrWrtFWfCry8Krg_yoWDGry3pr sxZFy7Gr18Jr15A345Ja1YgFy5AwsxArZ8WF45Cr1xA3yDA3s3Ww1ktr40qFyfZrW3WryI q3yIga1UuF4rJ3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: WAEOiPzeHLynhJw0MxrvyZkKx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299409; bh=0AXY11J0jQxHdvVAFgg1mxvyreg96A/hQWAfeyWLZiE=; h=Cc:Date:From:Reply-To:Subject:To; b=Ay263DHJrLZtLunYdlHJRSCbtbrRPRRRiF3O/8IY/GTDYMGsWVXso17z6CxGmcY7y56 63NaEaq8qa4QtguKA17ebaO25boB+inW0MDvmAdzqDyABrVLzUAP9cQD6M4x7bYYyAGWQ RF/fIggGlVt7idU4N+c6U6f+QnAWHjkbVL8= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299412333100039 Content-Type: text/plain; charset="utf-8" This library provides a delay interface and a timing interface. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../Include/Library/StableTimer.h | 43 ++++ .../Library/StableTimerLib/Count.S | 35 +++ .../Library/StableTimerLib/TimerLib.c | 242 ++++++++++++++++++ .../Library/StableTimerLib/TimerLib.inf | 28 ++ 4 files changed, 348 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/Stab= leTimer.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerL= ib/Count.S create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerL= ib/TimerLib.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerL= ib/TimerLib.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer= .h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer.h new file mode 100644 index 0000000000..09a2d07404 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer.h @@ -0,0 +1,43 @@ +/** @file + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Csr - Cpu Status Register + - Calc - Calculation + - Freq - frequency +**/ + +#ifndef STABLE_TIMER_H_ +#define STABLE_TIMER_H_ +#include "Library/Cpu.h" + +/** + Gets the timer count value. + + @param[] VOID + + @retval timer count value. +**/ +extern +UINTN +EFIAPI +LoongArchReadTime ( + VOID + ); + +/** + Calculate the timer frequency. + + @param[] VOID + + @retval Timer frequency. +**/ +UINT32 +EFIAPI +CalcConstFreq ( + VOID + ); +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Coun= t.S b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S new file mode 100644 index 0000000000..f22635712c --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S @@ -0,0 +1,35 @@ +#-------------------------------------------------------------------------= ----- +# +# Count for LoongArch +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#-------------------------------------------------------------------------= ----- + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif + +#include "Library/Cpu.h" +#include "LoongArchAsmMacro.h" +# +# Set cpu interrupts +# @param A0 The interrupt number +# +ASM_FUNC(CpuSetIP) + csrrd T0, LOONGARCH_CSR_ECFG + or T0, T0, A0 + csrwr T0, LOONGARCH_CSR_ECFG + jirl ZERO, RA,0 + +# +#Gets the timer count value. +# +#@param[] VOID +# +#@retval timer count value. +ASM_FUNC(LoongArchReadTime) + rdtime.d A0, ZERO + jirl ZERO, RA,0 diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Time= rLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib= .c new file mode 100644 index 0000000000..e758ae9d35 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.c @@ -0,0 +1,242 @@ +/** @file + Generic LoongArch implementation of TimerLib.h + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Freq - Frequency + - Csr - Cpu Status Register + - calc - calculate +**/ + +#include +#include +#include +#include +#include "Library/StableTimer.h" +#include "Library/Cpu.h" + +UINT32 StableTimerFreq =3D 0; + +/** + Calculate the timer frequency. + + @param[] VOID + + @retval Timer frequency. +**/ +UINT32 +EFIAPI +CalcConstFreq ( + VOID + ) +{ + UINT32 Result; + UINT32 BaseFreq; + UINT32 ClockMultiplier; + UINT32 ClockDivide; + + LOONGARCH_GET_CPUCFG (BaseFreq, LOONGARCH_CPUCFG4); + LOONGARCH_GET_CPUCFG (Result, LOONGARCH_CPUCFG5); + ClockMultiplier =3D Result & 0xffff; + ClockDivide =3D (Result >> 16) & 0xffff; + + if ((!BaseFreq) + || (!ClockMultiplier) + || (!ClockDivide)) + { + return 0; + } + else { + return (BaseFreq * ClockMultiplier / ClockDivide); + } +} +/** + Get the timer frequency. + + @param[] VOID + + @retval Timer frequency. +**/ +UINT32 +EFIAPI +GetFreq ( + VOID + ) +{ + if (StableTimerFreq) { + } else { + StableTimerFreq =3D CalcConstFreq (); + } + + return StableTimerFreq; +} + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return MicroSeconds + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + + UINTN Count; + UINTN Ticks; + UINTN Start; + UINTN End; + + Count =3D GetFreq (); + Count =3D (Count * MicroSeconds) / 1000000; + Start =3D CsrReadTime (); + End =3D Start + Count; + + do { + Ticks =3D CsrReadTime (); + } while (Ticks < End); + + return MicroSeconds; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return NanoSeconds + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + UINT32 MicroSeconds; + + if (NanoSeconds % 1000 =3D=3D 0) { + MicroSeconds =3D NanoSeconds/1000; + }else { + MicroSeconds =3D NanoSeconds/1000 + 1; + } + MicroSecondDelay (MicroSeconds); + + return NanoSeconds; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + Retrieves the current value of a 64-bit free running performance counter= . The + counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties (). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return CsrReadTime (); +} +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter s= tarts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end wi= th + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartV= alue + is less than EndValue, then the performance counter counts up. If StartV= alue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a Start= Value + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of = 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with bef= ore + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + if (StartValue !=3D NULL) { + *StartValue =3D BIT2; + } + + if (EndValue !=3D NULL) { + *EndValue =3D BIT48 - 1; + } + + return GetFreq (); +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter = to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance cou= nter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + UINT64 Frequency; + UINT64 NanoSeconds; + UINT64 Remainder; + INTN Shift; + + Frequency =3D GetPerformanceCounterProperties (NULL, NULL); + + // + // Ticks + // Time =3D --------- x 1,000,000,000 + // Frequency + // + NanoSeconds =3D MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remai= nder), 1000000000u); + + // + // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit. + // Since 2^29 < 1,000,000,000 =3D 0x3B9ACA00 < 2^30, Remainder should < = 2^(64-30) =3D 2^34, + // i.e. highest bit set in Remainder should <=3D 33. + // + Shift =3D MAX (0, HighBitSet64 (Remainder) - 33); + Remainder =3D RShiftU64 (Remainder, (UINTN) Shift); + Frequency =3D RShiftU64 (Frequency, (UINTN) Shift); + NanoSeconds +=3D DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u)= , Frequency, NULL); + + return NanoSeconds; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Time= rLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerL= ib.inf new file mode 100644 index 0000000000..fef0fac08c --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.inf @@ -0,0 +1,28 @@ +## @file +# Generic LoongArch implementation of TimerLib.h +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D TimerLib + FILE_GUID =3D 740389C7-CC44-4A2F-88DC-89D97D312E= 7C + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D TimerLib + +[Sources.common] + TimerLib.c + Count.S + +[Packages] + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + IoLib --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93897): https://edk2.groups.io/g/devel/message/93897 Mute This Topic: https://groups.io/mt/93715816/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93889+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93889+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299404; cv=none; d=zohomail.com; s=zohoarc; b=l2XHR0fsWOrsVdafKHzF7Q3/dhZyeHL9dilRCEOQLMrm9C9MsbFjOi7+Ad9MzHu8K20cAsXc8uXjjajkUKzkDV9FbjOf+uPy/7WdMANY6qHgqMIhhle14ZIlu9fLmJiQRwmED9BJIGHZ1oppkpvq2Fp3FlAWWZ3G73HvjPqwIhQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299404; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=voVRettu6GXyYHBtBAoPcsDZDL6geQEFmJVvn57Tqas=; b=hq0zWm4qYVCwPZt6mbRvo1V3dFby9JfcbDSc5qWERYSjXkUNPpazDV8omUxxH+x8RTmNN7HgzKzuxDsRyJXt16iTVa4fALKWPR8W25O5Rt1ea8uY+IV6j9VorXRZ/pgTF7XysnLIsZMg1KF7OcHDBn4hyMeikI1Qnec3UJ3zUo4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93889+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 166329940476762.36912517262954; Thu, 15 Sep 2022 20:36:44 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id lIZdYY1788612xTpf4oW1Nlm; Thu, 15 Sep 2022 20:36:43 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web08.2160.1663299401465115473 for ; Thu, 15 Sep 2022 20:36:42 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S9; Fri, 16 Sep 2022 11:36:39 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 07/16] Platform/Loongson: Support PEI phase. Date: Fri, 16 Sep 2022 11:36:24 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S9 X-Coremail-Antispam: 1UD129KBjvAXoWfAw1ktFy7Kw17JFWkXrWfGrg_yoW5WF17to W8JF92kw4UGr1rXw1UG3ZrtrWIvF1Yva1Yqr1rZayUAFs0yr13tF98t3s7Gw15AFn8Awn8 C3yfGaykJFW2q3s5n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: sS8kCfGE9mKM09ImXagpjP7Xx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299403; bh=dWDhmgtRetUd14OSJlzr80s9QUxS+vVz+5DA5UcDWz0=; h=Cc:Date:From:Reply-To:Subject:To; b=PSL5sSEp5KtWMDRwP2parG5/rADmEu5n4tadLRnikgaksBbAlB73VxqV2S6Afc2n1yO wwlgrnr/fsgFn7+5glscBZWotNYRKn/kaT1uJCh08Bbmg0RFsqxQjldCOmbjw1iPhJHPU iO16tAc1mayZZMOGmLbnRJy/Pim2gzSA1Fo= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299406325100014 Content-Type: text/plain; charset="utf-8" Platform PEI module for LoongArch platform initialization. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../Library/StableTimerLib/TimerLib.c | 6 +- .../Loongson/LoongArchQemuPkg/Loongson.dec | 22 ++ .../Loongson/LoongArchQemuPkg/Loongson.dsc | 66 ++++- .../Loongson/LoongArchQemuPkg/Loongson.fdf | 51 ++++ .../LoongArchQemuPkg/PlatformPei/Fv.c | 61 ++++ .../LoongArchQemuPkg/PlatformPei/MemDetect.c | 125 +++++++++ .../LoongArchQemuPkg/PlatformPei/Platform.c | 264 ++++++++++++++++++ .../LoongArchQemuPkg/PlatformPei/Platform.h | 87 ++++++ .../PlatformPei/PlatformPei.inf | 73 +++++ 9 files changed, 751 insertions(+), 4 deletions(-) create mode 100644 Platform/Loongson/LoongArchQemuPkg/PlatformPei/Fv.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetec= t.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform= .c create mode 100644 Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform= .h create mode 100644 Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform= Pei.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Time= rLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib= .c index e758ae9d35..660a5d8b0b 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.c +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.c @@ -98,11 +98,11 @@ MicroSecondDelay ( =20 Count =3D GetFreq (); Count =3D (Count * MicroSeconds) / 1000000; - Start =3D CsrReadTime (); + Start =3D LoongArchReadTime (); End =3D Start + Count; =20 do { - Ticks =3D CsrReadTime (); + Ticks =3D LoongArchReadTime (); } while (Ticks < End); =20 return MicroSeconds; @@ -154,7 +154,7 @@ GetPerformanceCounter ( VOID ) { - return CsrReadTime (); + return LoongArchReadTime (); } /** Retrieves the 64-bit frequency in Hz and the range of performance counter diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.dec index 248b668fd1..aca53583f1 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec @@ -30,9 +30,31 @@ [PcdsFixedAtBuild, PcdsDynamic] gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase|0x0|UINT64|0x00000003 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize|0x0|UINT32|0x00000004 + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvBase|0x0|UINT64|0x00000008 + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvSize|0x0|UINT32|0x00000009 gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0|UINT3= 2|0x00000016 gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|0|UI= NT32|0x00000017 + gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase|0x0|UINT64|0x00000018 + gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreePadding|256|UINT32|0x000000= 19 + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase|0|UINT64|0x0000001c gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize|0|UINT32|0x0000001d + gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop|0x0|UINT64|0x0000001e + gLoongArchQemuPkgTokenSpaceGuid.PcdRamRegionsBottom|0x0|UINT64|0x00000022 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase|0x0|UINT64|0x00000028 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize|0x0|UINT32|0x00000029 + +[PcdsFixedAtBuild.LOONGARCH64] + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32|UINT8|0x00000010 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0|UINT8|0x00000011 + +[PcdsDynamic] + gLoongArchQemuPkgTokenSpaceGuid.PcdRamSize|0x40000000|UINT64|0x00000041 + gLoongArchQemuPkgTokenSpaceGuid.PcdFwCfgSelectorAddress|0x0|UINT64|0x000= 00042 + gLoongArchQemuPkgTokenSpaceGuid.PcdFwCfgDataAddress|0x0|UINT64|0x00000043 + gLoongArchQemuPkgTokenSpaceGuid.PcdSwapPageDir|0x0|UINT64|0x00000044 + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPgd|0x0|UINT64|0x00000045 + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPud|0x0|UINT64|0x00000046 + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPmd|0x0|UINT64|0x00000047 + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPte|0x0|UINT64|0x00000048 + diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.dsc index f23fed77e6..09b324c3f7 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc @@ -57,22 +57,58 @@ =20 [LibraryClasses.common] PcdLib | MdePkg/Library/BasePcdLibNull/BasePcd= LibNull.inf + TimerLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/StableTimerLib/TimerLib.inf PrintLib | MdePkg/Library/BasePrintLib/BasePrint= Lib.inf BaseMemoryLib | MdePkg/Library/BaseMemoryLib/BaseMemo= ryLib.inf =20 =20 BaseLib | MdePkg/Library/BaseLib/BaseLib.inf + PerformanceLib | MdePkg/Library/BasePerformanceLibNull= /BasePerformanceLibNull.inf PeCoffLib | MdePkg/Library/BasePeCoffLib/BasePeCo= ffLib.inf + CacheMaintenanceLib | MdePkg/Library/BaseCacheMaintenanceLi= b/BaseCacheMaintenanceLib.inf + UefiDecompressLib | MdePkg/Library/BaseUefiDecompressLib/= BaseUefiDecompressLib.inf PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPoin= tLib/BasePeCoffGetEntryPointLib.inf IoLib | MdePkg/Library/BaseIoLibIntrinsic/Bas= eIoLibIntrinsic.inf SerialPortLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/SerialPortLib/SerialPortLib.inf DebugPrintErrorLevelLib | MdePkg/Library/BaseDebugPrintErrorLev= elLib/BaseDebugPrintErrorLevelLib.inf + FdtLib | EmbeddedPkg/Library/FdtLib/FdtLib.inf PeCoffExtraActionLib | MdePkg/Library/BasePeCoffExtraActionL= ibNull/BasePeCoffExtraActionLibNull.inf DebugAgentLib | MdeModulePkg/Library/DebugAgentLibNul= l/DebugAgentLibNull.inf =20 DebugLib | MdePkg/Library/BaseDebugLibSerialPort= /BaseDebugLibSerialPort.inf =20 + PeiServicesLib | MdePkg/Library/PeiServicesLib/PeiServ= icesLib.inf +[LibraryClasses.common.SEC] + ReportStatusCodeLib | MdeModulePkg/Library/PeiReportStatusC= odeLib/PeiReportStatusCodeLib.inf + HobLib | MdePkg/Library/PeiHobLib/PeiHobLib.inf + MemoryAllocationLib | MdePkg/Library/PeiMemoryAllocationLib= /PeiMemoryAllocationLib.inf + +[LibraryClasses.common.PEI_CORE] + HobLib | MdePkg/Library/PeiHobLib/PeiHobLib.inf + PeiServicesTablePointerLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + MemoryAllocationLib | MdePkg/Library/PeiMemoryAllocationLib= /PeiMemoryAllocationLib.inf + PeiCoreEntryPoint | MdePkg/Library/PeiCoreEntryPoint/PeiC= oreEntryPoint.inf + ReportStatusCodeLib | MdeModulePkg/Library/PeiReportStatusC= odeLib/PeiReportStatusCodeLib.inf + OemHookStatusCodeLib | MdeModulePkg/Library/OemHookStatusCod= eLibNull/OemHookStatusCodeLibNull.inf + PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPoin= tLib/BasePeCoffGetEntryPointLib.inf + QemuFwCfgLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/QemuFwCfgLib/QemuFwCfgLib.inf + MmuLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/MmuLib/MmuBaseLibPei.inf + +[LibraryClasses.common.PEIM] + HobLib | MdePkg/Library/PeiHobLib/PeiHobLib.inf + PeiServicesTablePointerLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + MemoryAllocationLib | MdePkg/Library/PeiMemoryAllocationLib= /PeiMemoryAllocationLib.inf + PeimEntryPoint | MdePkg/Library/PeimEntryPoint/PeimEnt= ryPoint.inf + ReportStatusCodeLib | MdeModulePkg/Library/PeiReportStatusC= odeLib/PeiReportStatusCodeLib.inf + OemHookStatusCodeLib | MdeModulePkg/Library/OemHookStatusCod= eLibNull/OemHookStatusCodeLibNull.inf + PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPoin= tLib/BasePeCoffGetEntryPointLib.inf + PeiResourcePublicationLib | MdePkg/Library/PeiResourcePublication= Lib/PeiResourcePublicationLib.inf + ExtractGuidedSectionLib | MdePkg/Library/PeiExtractGuidedSectio= nLib/PeiExtractGuidedSectionLib.inf + PcdLib | MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + QemuFwCfgS3Lib | OvmfPkg/Library/QemuFwCfgS3Lib/PeiQem= uFwCfgS3LibFwCfg.inf + QemuFwCfgLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/QemuFwCfgLib/QemuFwCfgLib.inf =20 + MmuLib | Platform/Loongson/LoongArchQemuPkg/Librar= y/MmuLib/MmuBaseLibPei.inf =20 =20 ##########################################################################= ###### @@ -119,11 +155,19 @@ # ASSERT_BREAKPOINT_ENABLED 0x10 # ASSERT_DEADLOOP_ENABLED 0x20 =20 +##########################################################################= ############# + gLoongArchQemuPkgTokenSpaceGuid.PcdRamRegionsBottom | 0= x90000000 gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress | 0= x90000000 gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize | 0= x10000 gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase | 0= x90010000 gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize | 0= x10000 - + gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase | 0= x1c400000 + # + # minimal memory for uefi bios should be 512M + # 0x00000000 - 0x10000000 + # 0x90000000 - 0xA0000000 + # + gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop | 0= xA0000000 =20 [Components] =20 @@ -131,3 +175,23 @@ # SEC Phase modules # Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf + + # + # PEI Phase modules + # + MdeModulePkg/Core/Pei/PeiMain.inf + MdeModulePkg/Universal/PCD/Pei/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf { + + NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompre= ssLib.inf + } + + Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf { + + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + } + diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.fdf index 128b3843db..f964304fdc 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf @@ -45,9 +45,60 @@ READ_LOCK_STATUS =3D TRUE =20 INF Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf =20 +##########################################################################= ########################### +[FV.PEIFV] +FvNameGuid =3D 6f856a84-de7d-4af9-93a3-342b4ecb46eb +BlockSize =3D $(BLOCK_SIZE) +FvAlignment =3D 16 +ERASE_POLARITY =3D 1 +MEMORY_MAPPED =3D TRUE +STICKY_WRITE =3D TRUE +LOCK_CAP =3D TRUE +LOCK_STATUS =3D TRUE +READ_DISABLED_CAP =3D TRUE +READ_ENABLED_CAP =3D TRUE +READ_STATUS =3D TRUE +READ_LOCK_CAP =3D TRUE +READ_LOCK_STATUS =3D TRUE +WRITE_DISABLED_CAP =3D TRUE +WRITE_ENABLED_CAP =3D TRUE +WRITE_STATUS =3D TRUE +WRITE_LOCK_CAP =3D TRUE +WRITE_LOCK_STATUS =3D TRUE + +APRIORI PEI { + INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf +} + +# +# PEI Phase modules +# + +INF MdeModulePkg/Core/Pei/PeiMain.inf +INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf +INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +INF Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf + ##########################################################################= ########################### [Rule.Common.SEC] FILE SEC =3D $(NAMED_GUID) { TE TE Align =3D Auto $(INF_OUTPUT)/$(MODULE_NAME).efi UI STRING =3D"$(MODULE_NAME)" Optional } + +##########################################################################= ########################### +[Rule.Common.PEI_CORE] + FILE PEI_CORE =3D $(NAMED_GUID) { + TE TE Align=3DAuto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING =3D"$(MODULE_NAME)" Optional + } + +##########################################################################= ########################### +[Rule.Common.PEIM] + FILE PEIM =3D $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 Align=3DAuto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING=3D"$(MODULE_NAME)" Optional + } + +##########################################################################= ########################### diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Fv.c b/Platform= /Loongson/LoongArchQemuPkg/PlatformPei/Fv.c new file mode 100644 index 0000000000..f79d4506b1 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Fv.c @@ -0,0 +1,61 @@ +/** @file + Build FV related hobs for platform. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "PiPei.h" +#include "Platform.h" +#include +#include +#include +#include + + +/** + Publish PEI & DXE (Decompressed) Memory based FVs to let PEI + and DXE know about them. + + @retval EFI_SUCCESS Platform PEI FVs were initialized successfully. + +**/ +EFI_STATUS +PeiFvInitialization ( + VOID + ) +{ + DEBUG ((DEBUG_INFO, "Platform PEI Firmware Volume Initialization\n")); + + // + // Create a memory allocation HOB for the PEI FV. + // + BuildMemoryAllocationHob ( + PcdGet64 (PcdSecPeiTempRamBase), + PcdGet32 (PcdSecPeiTempRamSize), + EfiBootServicesData + ); + + // + // Let DXE know about the DXE FV + // + BuildFvHob (PcdGet64 (PcdFlashDxeFvBase), PcdGet32 (PcdFlashDxeFvSize)); + + // + // Let PEI know about the DXE FV so it can find the DXE Core + // + DEBUG ((DEBUG_INFO, "DXEFV base:%p size:%x\n", (VOID *) (UINTN)PcdGet64 = (PcdFlashDxeFvBase), + PcdGet32 (PcdFlashDxeFvSize))); + PeiServicesInstallFvInfoPpi ( + NULL, + (VOID *) (UINTN)PcdGet64 (PcdFlashDxeFvBase), + PcdGet32 (PcdFlashDxeFvSize), + NULL, + NULL + ); + + return EFI_SUCCESS; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c b/P= latform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c new file mode 100644 index 0000000000..1010681d27 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c @@ -0,0 +1,125 @@ +/** @file + Memory Detection for Virtual Machines. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +// +// The package level header files this module uses +// +#include + +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Platform.h" + +/** + Publish PEI core memory + + @return EFI_SUCCESS The PEIM initialized successfully. + +**/ +EFI_STATUS +PublishPeiMemory ( + VOID + ) +{ + EFI_STATUS Status; + UINT64 Base; + UINT64 Size; + UINT64 RamTop; + + // + // Determine the range of memory to use during PEI + // + Base =3D PcdGet64 (PcdSecPeiTempRamBase) + PcdGet32 (PcdSecPeiTempRamSiz= e); + RamTop =3D PcdGet64 (PcdUefiRamTop); + Size =3D RamTop - Base; + + + // + // Publish this memory to the PEI Core + // + Status =3D PublishSystemMemory (Base, Size); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "Publish Memory Initialize done.\n")); + return Status; +} + +/** + Peform Memory Detection + Publish system RAM and reserve memory regions +**/ +VOID +InitializeRamRegions ( + VOID + ) +{ + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + LOONGARCH_MEMMAP_ENTRY MemoryMapEntry; + LOONGARCH_MEMMAP_ENTRY *StartEntry; + LOONGARCH_MEMMAP_ENTRY *pEntry; + UINTN Processed; + + Status =3D QemuFwCfgFindFile ("etc/memmap", &FwCfgItem, &FwCfgSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a %d read etc/memmap error Status %d \n", __fun= c__, __LINE__, Status)); + return ; + } + if (FwCfgSize % sizeof MemoryMapEntry !=3D 0) { + DEBUG ((DEBUG_ERROR, "no MemoryMapEntry FwCfgSize:%d\n", FwCfgSize)); + return ; + } + + QemuFwCfgSelectItem (FwCfgItem); + StartEntry =3D AllocatePages (EFI_SIZE_TO_PAGES (FwCfgSize)); + QemuFwCfgReadBytes (FwCfgSize, StartEntry); + for (Processed =3D 0; Processed < (FwCfgSize / sizeof MemoryMapEntry); P= rocessed++) { + pEntry =3D StartEntry + Processed; + if (pEntry->Length =3D=3D 0) { + continue; + } + + DEBUG ((DEBUG_INFO, "MemmapEntry Base %p length %p type %d\n", pEntry= ->BaseAddr, pEntry->Length, pEntry->Type)); + if (pEntry->Type !=3D EfiAcpiAddressRangeMemory) { + continue; + } + + AddMemoryRangeHob ( pEntry->BaseAddr, pEntry->BaseAddr + pEntry->Lengt= h); + } + + // + // Lock the scope of the cache. + // + BuildMemoryAllocationHob ( + PcdGet64 (PcdSecPeiTempRamBase), + PcdGet32 (PcdSecPeiTempRamSize), + EfiACPIMemoryNVS + ); + + // + // SEC stores its table of GUIDed section handlers here. + // + BuildMemoryAllocationHob ( + PcdGet64 (PcdGuidedExtractHandlerTableAddress), + PcdGet32 (PcdGuidedExtractHandlerTableSize), + EfiACPIMemoryNVS + ); +} diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c b/Pl= atform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c new file mode 100644 index 0000000000..6f6c53fcab --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c @@ -0,0 +1,264 @@ +/** @file + Platform PEI driver + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Mem - Memory +**/ + + +// +// The package level header files this module uses +// +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Platform.h" + +/* TODO */ +EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] =3D { + { EfiReservedMemoryType, 0x004 }, + { EfiRuntimeServicesData, 0x024 }, + { EfiRuntimeServicesCode, 0x030 }, + { EfiBootServicesCode, 0x180 }, + { EfiBootServicesData, 0xF00 }, + { EfiMaxMemoryType, 0x000 } +}; + +// +// Module globals +// +CONST EFI_PEI_PPI_DESCRIPTOR mPpiListBootMode =3D { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMasterBootModePpiGuid, + NULL +}; + +/** + Create Reserved type memory range hand off block. + + @param MemoryBase memory base address. + @param MemoryLimit memory length. + + @return VOID +**/ +VOID +AddReservedMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_RESERVED, + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED, + MemoryBase, + MemorySize + ); +} +/** + Create system type memory range hand off block. + + @param MemoryBase memory base address. + @param MemoryLimit memory length. + + @return VOID +**/ +VOID +AddMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED, + MemoryBase, + MemorySize + ); +} + +/** + Create memory range hand off block. + + @param MemoryBase memory base address. + @param MemoryLimit memory length. + + @return VOID +**/ +VOID +AddMemoryRangeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + EFI_PHYSICAL_ADDRESS MemoryLimit + ) +{ + AddMemoryBaseSizeHob (MemoryBase, (UINT64) (MemoryLimit - MemoryBase)); +} +/** + Create memory type information hand off block. + + @param VOID + + @return VOID +**/ +VOID +MemMapInitialization ( + VOID + ) +{ + DEBUG ((DEBUG_INFO, "=3D=3D%a=3D=3D\n", __func__)); + // + // Create Memory Type Information HOB + // + BuildGuidDataHob ( + &gEfiMemoryTypeInformationGuid, + mDefaultMemoryTypeInformation, + sizeof (mDefaultMemoryTypeInformation) + ); +} + +/** + Misc Initialization. + + @param VOID + + @return VOID +**/ +VOID +MiscInitialization ( + VOID + ) +{ + DEBUG ((DEBUG_INFO, "=3D=3D%a=3D=3D\n", __func__)); + // + // Creat CPU HOBs. + // + BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize= )); +} +/** + add fdt hand off block. + + @param VOID + + @return VOID +**/ +VOID +AddFdtHob (VOID) +{ + VOID *Base; + VOID *NewBase; + UINTN FdtSize; + UINTN FdtPages; + UINT64 *FdtHobData; + + Base =3D (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeBase); + ASSERT (Base !=3D NULL); + + FdtSize =3D fdt_totalsize (Base) + PcdGet32 (PcdDeviceTreePadding); + FdtPages =3D EFI_SIZE_TO_PAGES (FdtSize); + NewBase =3D AllocatePages (FdtPages); + ASSERT (NewBase !=3D NULL); + fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages)); + + FdtHobData =3D BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData); + ASSERT (FdtHobData !=3D NULL); + *FdtHobData =3D (UINTN)NewBase; + +} + +/** + Fetch the size of system memory from QEMU. + + @param VOID + + @return VOID +**/ +VOID +SystemMemorySizeInitialization ( + VOID + ) +{ + UINT64 RamSize; + RETURN_STATUS PcdStatus; + + QemuFwCfgSelectItem (QemuFwCfgItemRamSize); + RamSize=3D QemuFwCfgRead64 (); + DEBUG ((DEBUG_INFO, "%a: QEMU reports %dM system memory\n", __FUNCTION__, + RamSize/1024/1024)); + + // + // If the fw_cfg key or fw_cfg entirely is unavailable, no change to PCD. + // + if (RamSize =3D=3D 0) { + return; + } + + // + // Otherwise, set RamSize to PCD. + // + PcdStatus =3D PcdSet64S (PcdRamSize, RamSize); + ASSERT_RETURN_ERROR (PcdStatus); +} + +/** + Perform Platform PEI initialization. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @return EFI_SUCCESS The PEIM initialized successfully. + +**/ +EFI_STATUS +EFIAPI +InitializePlatform ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n")); + + Status =3D PeiServicesInstallPpi (&mPpiListBootMode); + ASSERT_EFI_ERROR (Status); + + SystemMemorySizeInitialization (); + PublishPeiMemory (); + PeiFvInitialization (); + InitializeRamRegions (); + MemMapInitialization (); + MiscInitialization (); + AddFdtHob (); + ConfigureMmu (); + + return EFI_SUCCESS; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.h b/Pl= atform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.h new file mode 100644 index 0000000000..bc44f233e7 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.h @@ -0,0 +1,87 @@ +/** @file + Platform PEI module include file. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef PLATFORM_H_ +#define PLATFORM_H_ + +#include + +/** + Create system type memory range hand off block. + + @param MemoryBase memory base address. + @param MemoryLimit memory length. + + @return VOID +**/ +VOID +AddMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ); + +/** + Create memory range hand off block. + + @param MemoryBase memory base address. + @param MemoryLimit memory length. + + @return VOID +**/ +VOID +AddMemoryRangeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + EFI_PHYSICAL_ADDRESS MemoryLimit + ); + +/** + Create Reserved type memory range hand off block. + + @param MemoryBase memory base address. + @param MemoryLimit memory length. + + @return VOID +**/ +VOID +AddReservedMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ); +/** + Publish PEI core memory + + @return EFI_SUCCESS The PEIM initialized successfully. + +**/ +EFI_STATUS +PublishPeiMemory ( + VOID + ); +/** + Publish system RAM and reserve memory regions + +**/ +VOID +InitializeRamRegions ( + VOID + ); + +/** + Publish PEI & DXE (Decompressed) Memory based FVs to let PEI + and DXE know about them. + + @retval EFI_SUCCESS Platform PEI FVs were initialized successfully. + +**/ +EFI_STATUS +PeiFvInitialization ( + VOID + ); + +#endif // _PLATFORM_PEI_H_INCLUDED_ diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf= b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf new file mode 100644 index 0000000000..47ee7e26d4 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf @@ -0,0 +1,73 @@ + +## @file +# Platform PEI driver +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PlatformPei + FILE_GUID =3D 4c0e81e5-e8e3-4eef-b24b-19b686e9ab53 + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D InitializePlatform + +[Sources] + Fv.c + MemDetect.c + Platform.c + + +[Packages] + ArmVirtPkg/ArmVirtPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + OvmfPkg/OvmfPkg.dec + +[Ppis] + gEfiPeiMasterBootModePpiGuid + +[Guids] + gEfiMemoryTypeInformationGuid + gFdtHobGuid + +[LibraryClasses] + DebugLib + BaseMemoryLib + HobLib + IoLib + PeiResourcePublicationLib + PeiServicesLib + PeiServicesTablePointerLib + PeimEntryPoint + QemuFwCfgLib + PcdLib + TimerLib + MmuLib + MemoryAllocationLib + +[Pcd] + gLoongArchQemuPkgTokenSpaceGuid.PcdRamSize + gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase + gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreePadding + +[FixedPcd] + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvBase + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvSize + gLoongArchQemuPkgTokenSpaceGuid.PcdRamRegionsBottom + gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize + gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize + gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize + +[Depex] + TRUE --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93889): https://edk2.groups.io/g/devel/message/93889 Mute This Topic: https://groups.io/mt/93715807/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93890+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93890+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299404; cv=none; d=zohomail.com; s=zohoarc; b=jZXU/eAhlgiaoDAqNMzpDuMTfsZ5KrSKgvXmxCA67/He6uZKEOT//iTLftb2OjnBxQ+qiuzZSp1DHv5CLQG/w27ANgU6aD2Sm6JOJkrVZNlCfCzGABLa/i0tDPLHUiFr65qn/VAGhukWvBA48ZEEOtK7V3yLNULtOc9Il/Cd7rA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299404; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=BPQdi+iFAZbWYJ1lbd47YtCD04nIozIrZ59U83wFSR8=; b=PCh3haD15r5HMoZKoFqT2q4qINYSQoDmpEOsF6ik0Gx7v6Amlpm2apaQ4jC17YX5RY5C4KQAHsSZdXBkJeNp8oTaltXB4ePco0bVn7XJMSsHwprmhFVvymZHq7kjXj7U+E9N30q4Y/th6EXKkNLsp+TPPpmwis+rEensh7hcWo0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93890+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299404491523.2336156059641; Thu, 15 Sep 2022 20:36:44 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 1P9qYY1788612x52xV8q3xjM; Thu, 15 Sep 2022 20:36:44 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web08.2161.1663299402050750329 for ; Thu, 15 Sep 2022 20:36:43 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S10; Fri, 16 Sep 2022 11:36:40 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 08/16] Platform/Loongson: Add CPU DXE driver. Date: Fri, 16 Sep 2022 11:36:25 +0800 Message-Id: <8934e119f73c3e178aa60e3e407498bb7ca4dd93.1663298005.git.lixianglai@loongson.cn> In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S10 X-Coremail-Antispam: 1UD129KBjvAXoWDAFWxKr1kZw1xXF15XFyrJFb_yoWrZrWfJo W5ZFZayw4xJw18Aa97G3Z3Ga4xXF18uFsYqrsYqFsYgr90gF15CFW0y3ZxGw1fJF45XrZx JFyxXas7CFZxXrn5n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: t69MQR78QqG7B4HYzDYEKwjEx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299404; bh=PdFI6WClClgBFYMBr5QBJJ8pl/zmV8Hqe81sDaKMVeU=; h=Cc:Date:From:Reply-To:Subject:To; b=B2c+4xKoVj1V/roC3q8TSO695GfZa2Y1N05lPLf+dyPAv5xn+cvLTNUiKUEWJ7PLZ9X wUigW1MuzTAVbSQOHy+u9Revifh6QM89m0nrQX7wqkMYMaRZFeo3r0IfbUwIQoElBs8Hs a9Mg1wwnvngs/HR7nzjb/M7vQla8YtbI2AA= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299406291100012 Content-Type: text/plain; charset="utf-8" The driver produces EFI_CPU_ARCH_PROTOCOL, Initialize the exception entry address. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c | 382 ++++++++++++++++++ .../LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h | 153 +++++++ .../Drivers/CpuDxe/CpuDxe.inf | 56 +++ .../Drivers/CpuDxe/LoongArch64/Exception.c | 336 +++++++++++++++ .../Drivers/CpuDxe/LoongArch64/Fpu.S | 67 +++ .../Drivers/CpuDxe/LoongArch64/LoongArch.S | 292 +++++++++++++ 6 files changed, 1286 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDx= e.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDx= e.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDx= e.inf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Loong= Arch64/Exception.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Loong= Arch64/Fpu.S create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/Loong= Arch64/LoongArch.S diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c b/P= latform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c new file mode 100644 index 0000000000..bff2bd0c0a --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.c @@ -0,0 +1,382 @@ +/** @file + CPU DXE Module to produce CPU ARCH Protocol + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "CpuDxe.h" + +BOOLEAN mInterruptState =3D FALSE; + +/* + This function flushes the range of addresses from Start to Start+Length + from the processor's data cache. If Start is not aligned to a cache line + boundary, then the bytes before Start to the preceding cache line bounda= ry + are also flushed. If Start+Length is not aligned to a cache line boundar= y, + then the bytes past Start+Length to the end of the next cache line bound= ary + are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate mu= st be + supported. If the data cache is fully coherent with all DMA operations, = then + this function can just return EFI_SUCCESS. If the processor does not sup= port + flushing a range of the data cache, then the entire data cache can be fl= ushed. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param Start The beginning physical address to flush from th= e processor's data + cache. + @param Length The number of bytes to flush from the processor= 's data cache. This + function may flush more bytes than Length speci= fies depending upon + the granularity of the flush operation that the= processor supports. + @param FlushType Specifies the type of flush operation to perfor= m. + + @retval EFI_SUCCESS The address range from Start to Start+Leng= th was flushed from + the processor's data cache. + @retval EFI_UNSUPPORTEDT The processor does not support the cache f= lush type specified + by FlushType. + @retval EFI_DEVICE_ERROR The address range from Start to Start+Leng= th could not be flushed + from the processor's data cache. + +**/ +EFI_STATUS +EFIAPI +CpuFlushCpuDataCache ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ) +{ + + switch (FlushType) { + case EfiCpuFlushTypeWriteBack: + WriteBackDataCacheRange ((VOID *) (UINTN)Start, (UINTN)Length); + break; + case EfiCpuFlushTypeInvalidate: + InvalidateDataCacheRange ((VOID *) (UINTN)Start, (UINTN)Length); + break; + case EfiCpuFlushTypeWriteBackInvalidate: + WriteBackInvalidateDataCacheRange ((VOID *) (UINTN)Start, (UINTN)Len= gth); + break; + default: + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + + +/** + This function enables interrupt processing by the processor. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS Interrupts are enabled on the processor. + @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the pro= cessor. + +**/ +EFI_STATUS +EFIAPI +CpuEnableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +{ + EnableInterrupts (); + + mInterruptState =3D TRUE; + return EFI_SUCCESS; +} + + +/** + This function disables interrupt processing by the processor. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS Interrupts are disabled on the processor. + @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the pr= ocessor. + +**/ +EFI_STATUS +EFIAPI +CpuDisableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +{ + DisableInterrupts (); + + mInterruptState =3D FALSE; + return EFI_SUCCESS; +} + + +/** + This function retrieves the processor's current interrupt state a return= s it in + State. If interrupts are currently enabled, then TRUE is returned. If in= terrupts + are currently disabled, then FALSE is returned. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param State A pointer to the processor's current interrupt = state. Set to TRUE if + interrupts are enabled and FALSE if interrupts = are disabled. + + @retval EFI_SUCCESS The processor's current interrupt state wa= s returned in State. + @retval EFI_INVALID_PARAMETER State is NULL. + +**/ +EFI_STATUS +EFIAPI +CpuGetInterruptState ( + IN EFI_CPU_ARCH_PROTOCOL *This, + OUT BOOLEAN *State + ) +{ + if (State =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + *State =3D mInterruptState; + return EFI_SUCCESS; +} + + +/** + This function generates an INIT on the processor. If this function succe= eds, then the + processor will be reset, and control will not be returned to the caller.= If InitType is + not supported by this processor, or the processor cannot programmaticall= y generate an + INIT without help from external hardware, then EFI_UNSUPPORTED is return= ed. If an error + occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param InitType The type of processor INIT to perform. + + @retval EFI_SUCCESS The processor INIT was performed. This ret= urn code should never be seen. + @retval EFI_UNSUPPORTED The processor INIT operation specified by = InitType is not supported + by this processor. + @retval EFI_DEVICE_ERROR The processor INIT failed. + +**/ +EFI_STATUS +EFIAPI +CpuInit ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_INIT_TYPE InitType + ) +{ + return EFI_UNSUPPORTED; +} + +/** + This function registers and enables the handler specified by InterruptHa= ndler for a processor + interrupt or exception type specified by InterruptType. If InterruptHand= ler is NULL, then the + handler for the processor interrupt or exception type specified by Inter= ruptType is uninstalled. + The installed handler is called once for each processor interrupt or exc= eption. + + @param InterruptType Interrupt Type. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRU= PT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the h= andler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt wa= s successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handle= r for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler fo= r InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType i= s not supported. +**/ +EFI_STATUS +EFIAPI +CpuRegisterInterruptHandler ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + + return RegisterInterruptHandler (InterruptType, InterruptHandler); +} + +/** + Returns a timer value from one of the CPU's internal timers. There is no + inherent time interval between ticks but is a function of the CPU freque= ncy. + + @param This - Protocol instance structure. + @param TimerIndex - Specifies which CPU timer is requested. + @param TimerValue - Pointer to the returned timer value. + @param TimerPeriod - A pointer to the amount of time that passes + in femtoseconds (10-15) for each increment + of TimerValue. If TimerValue does not + increment at a predictable rate, then 0 is + returned. The amount of time that has + passed between two calls to GetTimerValue() + can be calculated with the formula + (TimerValue2 - TimerValue1) * TimerPeriod. + This parameter is optional and may be NULL. + + @retval EFI_SUCCESS - If the CPU timer count was returned. + @retval EFI_UNSUPPORTED - If the CPU does not have any readable ti= mers. + @retval EFI_DEVICE_ERROR - If an error occurred while reading the t= imer. + @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is= NULL. +**/ +EFI_STATUS +EFIAPI +CpuGetTimerValue ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} +/** + This function modifies the attributes for the memory region specified by= BaseAddress and + Length from their current attributes to the attributes specified by Attr= ibutes. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param BaseAddress The physical address that is the start address = of a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memor= y region. + + @retval EFI_SUCCESS The attributes were set for the memory reg= ion. + @retval EFI_ACCESS_DENIED The attributes for the memory resource ran= ge specified by + BaseAddress and Length cannot be modified. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to m= odify the attributes of + the memory resource range. + @retval EFI_UNSUPPORTED The processor does not support one or more= bytes of the memory + resource range specified by BaseAddress an= d Length. + The bit mask of attributes is not support = for the memory resource + range specified by BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +CpuSetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 EfiAttributes + ) +{ + EFI_STATUS Status; + UINTN LoongArchAttributes; + UINTN RegionBaseAddress; + UINTN RegionLength; + UINTN RegionLoongArchAttributes; + + if ((BaseAddress & (SIZE_4KB - 1)) !=3D 0) { + // Minimum granularity is SIZE_4KB (4KB on ARM) + DEBUG ((DEBUG_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx): Minimum gr= anularity is SIZE_4KB\n", + BaseAddress, + Length, + EfiAttributes)); + + return EFI_UNSUPPORTED; + } + // Convert the 'Attribute' into LoongArch Attribute + LoongArchAttributes =3D EfiAttributeToLoongArchAttribute (EfiAttributes); + + // Get the region starting from 'BaseAddress' and its 'Attribute' + RegionBaseAddress =3D BaseAddress; + Status =3D GetLoongArchMemoryRegion (RegionBaseAddress, BaseAddress + Le= ngth, + &RegionLength, &RegionLoongArchAttributes); + + LoongArchSetMemoryAttributes (BaseAddress, Length, EfiAttributes); + // Data & Instruction Caches are flushed when we set new memory attribut= es. + // So, we only set the attributes if the new region is different. + if (EFI_ERROR (Status) || (RegionLoongArchAttributes !=3D LoongArchAttri= butes) || + ((BaseAddress + Length) > (RegionBaseAddress + RegionLength))) + { + return LoongArchSetMemoryAttributes (BaseAddress, Length, EfiAttribute= s); + } + return EFI_SUCCESS; +} + +/** + Callback function for idle events. + + @param Event Event whose notification function is being= invoked. + @param Context The pointer to the notification function's= context, + which is implementation-dependent. + + @param VOID +**/ +VOID +EFIAPI +IdleLoopEventCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + CpuSleep (); +} + +// +// Globals used to initialize the protocol +// +EFI_HANDLE CpuHandle =3D NULL; +EFI_CPU_ARCH_PROTOCOL Cpu =3D { + CpuFlushCpuDataCache, + CpuEnableInterrupt, + CpuDisableInterrupt, + CpuGetInterruptState, + CpuInit, + CpuRegisterInterruptHandler, + CpuGetTimerValue, + CpuSetMemoryAttributes, + 0, // NumberOfTimers + 4, // DmaBufferAlignment +}; + + +/** + Initialize the state information for the CPU Architectural Protocol. + + @param ImageHandle Image handle this driver. + @param SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS Thread can be successfully created + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Cannot create the thread +**/ +EFI_STATUS +CpuDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT IdleLoopEvent; + + InitializeExceptions (&Cpu); + + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &CpuHandle, + &gEfiCpuArchProtocolGuid, &Cpu, + NULL + ); + + // + // Setup a callback for idle events + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + IdleLoopEventCallback, + NULL, + &gIdleLoopEventGuid, + &IdleLoopEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h b/P= latform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h new file mode 100644 index 0000000000..062f366ba2 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.h @@ -0,0 +1,153 @@ +/** @file + CPU DXE Module to produce CPU ARCH Protocol and CPU MP Protocol + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef CPU_DXE_H_ +#define CPU_DXE_H_ + +#include + +/** + This function registers and enables the handler specified by InterruptHa= ndler for a processor + interrupt or exception type specified by InterruptType. If InterruptHand= ler is NULL, then the + handler for the processor interrupt or exception type specified by Inter= ruptType is uninstalled. + The installed handler is called once for each processor interrupt or exc= eption. + + @param InterruptType A pointer to the processor's current interrupt = state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disable= d. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRU= PT_HANDLER that is called + when a processor interrupt occurs. If this para= meter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt wa= s successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handle= r for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler fo= r InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType i= s not supported. + +**/ +EFI_STATUS +RegisterInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + + +/** + This function registers and enables the handler specified by InterruptHa= ndler for a processor + interrupt or exception type specified by InterruptType. If InterruptHand= ler is NULL, then the + handler for the processor interrupt or exception type specified by Inter= ruptType is uninstalled. + The installed handler is called once for each processor interrupt or exc= eption. + + @param InterruptType A pointer to the processor's current interrupt = state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disable= d. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRU= PT_HANDLER that is called + when a processor interrupt occurs. If this para= meter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt wa= s successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handle= r for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler fo= r InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType i= s not supported. + +**/ +EFI_STATUS +RegisterDebuggerInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + +/** + This function modifies the attributes for the memory region specified by= BaseAddress and + Length from their current attributes to the attributes specified by Attr= ibutes. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param BaseAddress The physical address that is the start address = of a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memor= y region. + + @retval EFI_SUCCESS The attributes were set for the memory reg= ion. + @retval EFI_ACCESS_DENIED The attributes for the memory resource ran= ge specified by + BaseAddress and Length cannot be modified. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to m= odify the attributes of + the memory resource range. + @retval EFI_UNSUPPORTED The processor does not support one or more= bytes of the memory + resource range specified by BaseAddress an= d Length. + The bit mask of attributes is not support = for the memory resource + range specified by BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +CpuSetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +/** Exception module initialization + This function sets the exception base address. + + @param Cpu A pointer to the CPU architecture protocol structure. + + @retval EFI_SUCCESS Initialization succeeded + @retval EFI_NOT_FOUND Could not Found resources. + @retval EFI_OUT_OF_RESOURCES No enough resources. +**/ +EFI_STATUS +InitializeExceptions ( + IN EFI_CPU_ARCH_PROTOCOL *Cpu + ); + +/** Common exception entry + Exception handling is the entry point for the C environment, + This function does different things depending on the exception type. + + @param SystemContext The system context at the time of the exception. + + @retval VOID. +**/ +VOID +EFIAPI +CommonExceptionEntry ( + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + +extern CHAR8 LoongArchException[], LoongArchExceptionEnd[]; +/** Set Exception Base Address + + @param addr Exception Base Address. + + @retval The Old Exception Base Address. +**/ +extern +UINT64 +SetEbase ( + EFI_PHYSICAL_ADDRESS addr + ); +/* + Load the FPU with signalling NANS. This bit pattern we're using has + the property that no matter whether considered as single or as double + precision represents signaling NANS. + + @param fcsr The value to initialize FCSR0 + + @retval The Old Exception Base Address. + */ +extern +VOID +InitFpu ( + UINT32 fcsr + ); + +#endif // __CPU_DXE_H__ diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.inf b= /Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.inf new file mode 100644 index 0000000000..a5e93efdeb --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.inf @@ -0,0 +1,56 @@ +## @file +# CPU driver installs CPU Architecture Protocol and CPU MP protocol. +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D CpuDxe + FILE_GUID =3D bf954921-25c1-48c0-9bfb-8d0cd7ee92da + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + + ENTRY_POINT =3D CpuDxeInitialize + +[Sources.Common] + CpuDxe.c + CpuDxe.h + +[Sources.LOONGARCH64] + LoongArch64/Exception.c + LoongArch64/LoongArch.S + LoongArch64/Fpu.S + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + CacheMaintenanceLib + CpuLib + DebugLib + DxeServicesTableLib + HobLib + PeCoffGetEntryPointLib + UefiDriverEntryPoint + UefiLib + MmuLib + +[Protocols] + gEfiCpuArchProtocolGuid + gEfiMpServiceProtocolGuid + +[Guids] + gEfiDebugImageInfoTableGuid + gIdleLoopEventGuid + +[Depex] + TRUE diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/= Exception.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64= /Exception.c new file mode 100644 index 0000000000..f626330f43 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/Excepti= on.c @@ -0,0 +1,336 @@ +/** @file + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - ESTAT - Exception Status + - ECFG - Exception Configure + - ERA - Exception Return Address + - BADV - Bad Virtual Address + - BADI - Bad Instructions + - Epc or EPC or epc - Exception Program Counter + - pc or PC or pc - Program Counter + - CRMD - Current Mode + - PRMD - Previous Mode + - CsrEuen - Cpu Status Register Extern Unit Enable + - fpu or fp or FP - Float Point Unit + - LOONGARCH - Loongson Arch + - Irq - Interrupt ReQuest +**/ + +#include "Library/Cpu.h" +#include +#include +#include +#include +#include +#include "CpuDxe.h" +#include +#include +#include + + + +EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_LOONGARCH_INTERRUPT + 1]; +EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_LOONGARCH_INTERRUPT= + 1]; + +/** + This function registers and enables the handler specified by InterruptHa= ndler for a processor + interrupt or exception type specified by InterruptType. If InterruptHand= ler is NULL, then the + handler for the processor interrupt or exception type specified by Inter= ruptType is uninstalled. + The installed handler is called once for each processor interrupt or exc= eption. + + @param InterruptType A pointer to the processor's current interrupt = state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disable= d. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRU= PT_HANDLER that is called + when a processor interrupt occurs. If this para= meter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt wa= s successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handle= r for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler fo= r InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType i= s not supported. + +**/ +EFI_STATUS +RegisterInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + if (InterruptType > MAX_LOONGARCH_INTERRUPT) { + return EFI_UNSUPPORTED; + } + + if ((InterruptHandler !=3D NULL) + && (gExceptionHandlers[InterruptType] !=3D NULL)) + { + return EFI_ALREADY_STARTED; + } + + gExceptionHandlers[InterruptType] =3D InterruptHandler; + + return EFI_SUCCESS; +} +/** + This function calls the corresponding exception handler based on the exc= eption type. + + @param ExceptionType Exception Type. + @param SystemContext The system context at the time of the exception. + + @retval VOID +**/ +STATIC VOID +EFIAPI +InterruptHandler ( + IN INT32 ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + INT32 Pending; + /*irq [13-0] NMI IPI TI PCOV hw IP10-IP2 soft IP1-IP0*/ + Pending =3D ((SystemContext.SystemContextLoongArch64->ESTAT) & + (SystemContext.SystemContextLoongArch64->ECFG) & 0x1fff); + if (Pending & (1 << 11/*TI*/)) { + gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext); + } else { + DEBUG ((DEBUG_INFO, "Pending: 0x%0x, ExceptionType: 0x%0x\n", Pendin= g, ExceptionType)); + } +} + +/** + Use the EFI Debug Image Table to lookup the FaultAddress and find which = PE/COFF image + it came from. As long as the PE/COFF image contains a debug directory en= try a + string can be returned. For ELF and Mach-O images the string points to t= he Mach-O or ELF + image. Microsoft tools contain a pointer to the PDB file that contains t= he debug information. + + @param FaultAddress Address to find PE/COFF image for. + @param ImageBase Return load address of found image + @param PeCoffSizeOfHeaders Return the size of the PE/COFF header for t= he image that was found + + @retval NULL FaultAddress not in a loaded PE/COFF image. + @retval Path and file name of PE/COFF image. + +**/ +CHAR8 * +GetImageName ( + IN UINTN FaultAddress, + OUT UINTN *ImageBase, + OUT UINTN *PeCoffSizeOfHeaders + ) +{ + EFI_STATUS Status; + EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *DebugTableHeader; + EFI_DEBUG_IMAGE_INFO *DebugTable; + UINTN Entry; + CHAR8 *Address; + + Status =3D EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid,= (VOID **)&DebugTableHeader); + if (EFI_ERROR (Status)) { + return NULL; + } + + DebugTable =3D DebugTableHeader->EfiDebugImageInfoTable; + if (DebugTable =3D=3D NULL) { + return NULL; + } + + Address =3D (CHAR8 *)(UINTN)FaultAddress; + for (Entry =3D 0; Entry < DebugTableHeader->TableSize; Entry++, DebugTab= le++) { + if (DebugTable->NormalImage !=3D NULL) { + if ((DebugTable->NormalImage->ImageInfoType =3D=3D EFI_DEBUG_IMAGE_I= NFO_TYPE_NORMAL) && + (DebugTable->NormalImage->LoadedImageProtocolInstance !=3D NULL)= ) { + if ((Address >=3D (CHAR8 *)DebugTable->NormalImage->LoadedImagePro= tocolInstance->ImageBase) && + (Address <=3D ((CHAR8 *)DebugTable->NormalImage->LoadedImagePr= otocolInstance->ImageBase + DebugTable->NormalImage->LoadedImageProtocolIns= tance->ImageSize))) { + *ImageBase =3D (UINTN)DebugTable->NormalImage->LoadedImageProtoc= olInstance->ImageBase; + *PeCoffSizeOfHeaders =3D PeCoffGetSizeOfHeaders ((VOID *)(UINTN)= *ImageBase); + return PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->Loade= dImageProtocolInstance->ImageBase); + } + } + } + } + + return NULL; +} + +/** + pass a file name string that contains the path, return file name. + + @param FullName Path and file name + + @retval file name. +**/ +STATIC +CONST CHAR8 * +BaseName ( + IN CONST CHAR8 *FullName + ) +{ + CONST CHAR8 *Str; + + Str =3D FullName + AsciiStrLen (FullName); + + while (--Str > FullName) { + if (*Str =3D=3D '/' || *Str =3D=3D '\\') { + return Str + 1; + } + } + return Str; +} + +/** Default Exception Handler Function + This function is called when an exception occurs that cannot be handled, + and this function prints the system context information when the interru= pt occurred + + @param SystemContext The system context at the time of the exception. + + @retval VOID. +**/ +STATIC +VOID +EFIAPI +DefaultHandler ( + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + CHAR8 *ImageName; + UINTN ImageBase, Epc; + UINTN PeCoffSizeOfHeader; + + DEBUG ((DEBUG_ERROR, "CRMD 0x%llx\n", SystemContext.SystemContextLoon= gArch64->CRMD)); + DEBUG ((DEBUG_ERROR, "PRMD 0x%llx\n", SystemContext.SystemContextLoon= gArch64->PRMD)); + DEBUG ((DEBUG_ERROR, "ECFG 0x%llx\n", SystemContext.SystemContextLoong= Arch64->ECFG)); + DEBUG ((DEBUG_ERROR, "ESTAT 0x%llx\n", SystemContext.SystemContextLoo= ngArch64->ESTAT)); + DEBUG ((DEBUG_ERROR, "ERA 0x%llx\n", SystemContext.SystemContextLoon= gArch64->ERA)); + DEBUG ((DEBUG_ERROR, "BADV 0x%llx\n", SystemContext.SystemContextLoo= ngArch64->BADV)); + DEBUG ((DEBUG_ERROR, "BADI 0x%llx\n", SystemContext.SystemContextLoongA= rch64->BADI)); + + Epc =3D SystemContext.SystemContextLoongArch64->ERA; + ImageName =3D GetImageName (Epc, &ImageBase, &PeCoffSizeOfHeader); + if (ImageName !=3D NULL) { + DEBUG ((DEBUG_ERROR, "PC 0x%012lx (0x%012lx+0x%08x) [ 0] %a\n", + Epc, ImageBase, + Epc - ImageBase, BaseName (ImageName))); + } else { + DEBUG ((DEBUG_ERROR, "PC 0x%012lx\n", Epc)); + } + + while (1); +} + +/** Common exception entry + Exception handling is the entry point for the C environment, + This function does different things depending on the exception type. + + @param SystemContext The system context at the time of the exception. + + @retval VOID. +**/ +VOID +EFIAPI +CommonExceptionEntry ( + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + INT32 ExceptionType; + UINT64 CsrEuen, FpuStatus; + + ExceptionType =3D SystemContext.SystemContextLoongArch64->ESTAT & CSR_ES= TAT_EXC; + ExceptionType =3D ExceptionType >> CSR_ESTAT_EXC_SHIFT; + + LOONGARCH_CSR_READQ (CsrEuen, LOONGARCH_CSR_EUEN); + FpuStatus =3D CsrEuen & CSR_EUEN_FPEN; + switch (ExceptionType) { + case EXC_INT: + /* + * handle interrupt exception + */ + InterruptHandler (ExceptionType, SystemContext); + if (!FpuStatus) { + LOONGARCH_CSR_READQ (CsrEuen, LOONGARCH_CSR_EUEN); + if (CsrEuen & CSR_EUEN_FPEN) { + /* + * Since Hw FP is enabled during interrupt handler, + * disable FP + */ + CsrEuen &=3D ~CSR_EUEN_FPEN; + LOONGARCH_CSR_WRITEQ (CsrEuen, LOONGARCH_CSR_EUEN); + } + } + break; + case EXC_FPDIS: + /* + * Hardware FP disabled exception, + * Enable and init FP registers here + */ + LOONGARCH_ENABLR_FPU (); + InitFpu(FPU_CSR_RN); + break; + default: + DefaultHandler(SystemContext); + break; + } +} + +/** Exception module initialization + This function sets the exception base address. + + @param Cpu A pointer to the CPU architecture protocol structure. + + @retval EFI_SUCCESS Initialization succeeded + @retval EFI_NOT_FOUND Could not Found resources. + @retval EFI_OUT_OF_RESOURCES No enough resources. +**/ +EFI_STATUS +InitializeExceptions ( + IN EFI_CPU_ARCH_PROTOCOL *Cpu + ) +{ + EFI_STATUS Status; + BOOLEAN IrqEnabled; + EFI_PHYSICAL_ADDRESS Address; + + ZeroMem (gExceptionHandlers, sizeof (*gExceptionHandlers)); + + // + // Disable interrupts + // + Cpu->GetInterruptState (Cpu, &IrqEnabled); + Cpu->DisableInterrupt (Cpu); + + // + // EFI does not use the FIQ, but a debugger might so we must disable + // as we take over the exception vectors. + // + Status =3D gBS->AllocatePages ( + AllocateAnyPages, + EfiRuntimeServicesData, + 1, + &Address + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((DEBUG_INFO, "Set Exception Base Address\n")); + CopyMem ((char *)Address, LoongArchException, (LoongArchExceptionEnd - L= oongArchException)); + InvalidateInstructionCacheRange ((char *)Address, (LoongArchExceptionEnd= - LoongArchException)); + + SetEbase (Address); + DEBUG ((DEBUG_INFO, "LoongArchException address: 0x%p\n", Address)); + DEBUG ((DEBUG_INFO, "LoongArchExceptionEnd address: 0x%p\n", Address + (= LoongArchExceptionEnd - LoongArchException))); + + DEBUG ((DEBUG_INFO, "InitializeExceptions, IrqEnabled =3D %x\n", IrqEnab= led)); + if (IrqEnabled) { + // + // Restore interrupt state + // + Status =3D Cpu->EnableInterrupt (Cpu); + } + + return Status; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/= Fpu.S b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/Fpu.S new file mode 100644 index 0000000000..f6cab5c9e7 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/Fpu.S @@ -0,0 +1,67 @@ +#-------------------------------------------------------------------------= ----- +# +# Fpu for LoongArch +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# @par Glossary: +# - CsrEuen - Cpu Status Register Extern Unit Enable +# - FPEN - FPU Enable +# - fpu or fp or FP - Float Point Unit +#-------------------------------------------------------------------------= ---- +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif +#include "Library/Cpu.h" +#include "CpuDxe.h" +#include "LoongArchAsmMacro.h" + +/* + Load the FPU with signalling NANS. This bit pattern we're using has + the property that no matter whether considered as single or as double + precision represents signaling NANS. + + The value to initialize FCSR0 to comes in $A0. + */ +ASM_FUNC(InitFpu) + li.d T1, CSR_EUEN_FPEN + csrxchg T1, T1, LOONGARCH_CSR_EUEN + + movgr2fcsr FCSR0, A0 + li.d T1, -1 # SNaN + movgr2fr.d $f0, T1 + movgr2fr.d $f1, T1 + movgr2fr.d $f2, T1 + movgr2fr.d $f3, T1 + movgr2fr.d $f4, T1 + movgr2fr.d $f5, T1 + movgr2fr.d $f6, T1 + movgr2fr.d $f7, T1 + movgr2fr.d $f8, T1 + movgr2fr.d $f9, T1 + movgr2fr.d $f10, T1 + movgr2fr.d $f11, T1 + movgr2fr.d $f12, T1 + movgr2fr.d $f13, T1 + movgr2fr.d $f14, T1 + movgr2fr.d $f15, T1 + movgr2fr.d $f16, T1 + movgr2fr.d $f17, T1 + movgr2fr.d $f18, T1 + movgr2fr.d $f19, T1 + movgr2fr.d $f20, T1 + movgr2fr.d $f21, T1 + movgr2fr.d $f22, T1 + movgr2fr.d $f23, T1 + movgr2fr.d $f24, T1 + movgr2fr.d $f25, T1 + movgr2fr.d $f26, T1 + movgr2fr.d $f27, T1 + movgr2fr.d $f28, T1 + movgr2fr.d $f29, T1 + movgr2fr.d $f30, T1 + movgr2fr.d $f31, T1 + + jirl ZERO, RA, 0 diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/= LoongArch.S b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64= /LoongArch.S new file mode 100644 index 0000000000..ae3e00b870 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/LoongArch64/LoongAr= ch.S @@ -0,0 +1,292 @@ +#-------------------------------------------------------------------------= ----- +# +# LoongArch for LoongArch +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# @par Glossary: +# - CsrEuen - Cpu Status Register Extern Unit Enable +# - fpu - Float Point Unit +# - LOONGARCH - Loongson Arch +# - Ebase - Exception Base Address +#-------------------------------------------------------------------------= ---- + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif + +#include "Library/Cpu.h" +#include "CpuDxe.h" +#include "LoongArchAsmMacro.h" + +#define RSIZE 8 /* 64 bit mode register size */ +#define RLOGSIZE 3 + + +/* + Main exception handler. Not really a leaf routine but not a normal + function either. Save away the entire cpu state end enter exception mod= e. + */ +ASM_FUNC(Exception_handler) + + csrrd SP, LOONGARCH_CSR_KS1 + + addi.d T0, $r0, -0x10 + and SP, SP, T0 + addi.d SP, SP, -((CSR_NUM + BASE_NUM + FP_BASE_NUM) * RSIZE) + + st.d RA, SP, RA_NUM * RSIZE + st.d GP, SP, GP_NUM * RSIZE + st.d A0, SP, A0_NUM * RSIZE + st.d A1, SP, A1_NUM * RSIZE + st.d A2, SP, A2_NUM * RSIZE + st.d A3, SP, A3_NUM * RSIZE + st.d A4, SP, A4_NUM * RSIZE + st.d A5, SP, A5_NUM * RSIZE + st.d A6, SP, A6_NUM * RSIZE + st.d A7, SP, A7_NUM * RSIZE + st.d T1, SP, T1_NUM * RSIZE + st.d T2, SP, T2_NUM * RSIZE + st.d T3, SP, T3_NUM * RSIZE + st.d T4, SP, T4_NUM * RSIZE + st.d T5, SP, T5_NUM * RSIZE + st.d T6, SP, T6_NUM * RSIZE + st.d T7, SP, T7_NUM * RSIZE + st.d T8, SP, T8_NUM * RSIZE + st.d TP, SP, TP_NUM * RSIZE + st.d FP, SP, FP_NUM * RSIZE + st.d S0, SP, S0_NUM * RSIZE + st.d S1, SP, S1_NUM * RSIZE + st.d S2, SP, S2_NUM * RSIZE + st.d S3, SP, S3_NUM * RSIZE + st.d S4, SP, S4_NUM * RSIZE + st.d S5, SP, S5_NUM * RSIZE + st.d S6, SP, S6_NUM * RSIZE + st.d S7, SP, S7_NUM * RSIZE + st.d S8, SP, S8_NUM * RSIZE + + /* + * save T0/SP from scratch registers on stack + */ + csrrd T0, LOONGARCH_CSR_KS0 + st.d T0, SP, T0_NUM * RSIZE + csrrd T0, LOONGARCH_CSR_KS1 + st.d T0, SP, SP_NUM * RSIZE + + csrrd T0, LOONGARCH_CSR_CRMD + st.d T0, SP, (LOONGARCH_CSR_CRMD + BASE_NUM) * RSIZE + csrrd T0, LOONGARCH_CSR_PRMD + st.d T0, SP, (LOONGARCH_CSR_PRMD + BASE_NUM) * RSIZE + csrrd T0, LOONGARCH_CSR_ECFG + st.d T0, SP, (LOONGARCH_CSR_ECFG + BASE_NUM) * RSIZE + csrrd T0, LOONGARCH_CSR_ESTAT + st.d T0, SP, (LOONGARCH_CSR_ESTAT + BASE_NUM) * RSIZE + csrrd T0, LOONGARCH_CSR_EPC + st.d T0, SP, (LOONGARCH_CSR_EPC+ BASE_NUM) * RSIZE + csrrd T0, LOONGARCH_CSR_BADV + st.d T0, SP, (LOONGARCH_CSR_BADV + BASE_NUM) * RSIZE + csrrd T0, LOONGARCH_CSR_BADI + st.d T0, SP, (LOONGARCH_CSR_BADI + BASE_NUM) * RSIZE + csrrd T0, LOONGARCH_CSR_EUEN + st.d T0, SP, (LOONGARCH_CSR_EUEN + BASE_NUM) * RSIZE + + /* Save FPU context */ + ori T1, ZERO, CSR_EUEN_FPEN + and T2, T0, T1 + beqz T2, 1f + + fst.d $f0, SP, (FP0_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f1, SP, (FP1_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f2, SP, (FP2_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f3, SP, (FP3_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f4, SP, (FP4_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f5, SP, (FP5_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f6, SP, (FP6_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f7, SP, (FP7_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f8, SP, (FP8_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f9, SP, (FP9_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f10, SP, (FP10_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f11, SP, (FP11_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f12, SP, (FP12_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f13, SP, (FP13_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f14, SP, (FP14_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f15, SP, (FP15_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f16, SP, (FP16_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f17, SP, (FP17_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f18, SP, (FP18_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f19, SP, (FP19_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f20, SP, (FP20_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f21, SP, (FP21_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f22, SP, (FP22_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f23, SP, (FP23_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f24, SP, (FP24_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f25, SP, (FP25_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f26, SP, (FP26_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f27, SP, (FP27_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f28, SP, (FP28_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f29, SP, (FP29_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f30, SP, (FP30_NUM + FP_BASE_INDEX) * RSIZE + fst.d $f31, SP, (FP31_NUM + FP_BASE_INDEX) * RSIZE + + movfcsr2gr T3, FCSR0 + st.d T3, SP, (FCSR_NUM + FP_BASE_INDEX) * RSIZE + movcf2gr T3, $fcc0 + or T2, T3, ZERO + movcf2gr T3, $fcc1 + bstrins.d T2, T3, 0xf, 0x8 + movcf2gr T3, $fcc2 + bstrins.d T2, T3, 0x17, 0x10 + movcf2gr T3, $fcc3 + bstrins.d T2, T3, 0x1f, 0x18 + movcf2gr T3, $fcc4 + bstrins.d T2, T3, 0x27, 0x20 + movcf2gr T3, $fcc5 + bstrins.d T2, T3, 0x2f, 0x28 + movcf2gr T3, $fcc6 + bstrins.d T2, T3, 0x37, 0x30 + movcf2gr T3, $fcc7 + bstrins.d T2, T3, 0x3f, 0x38 + st.d T2, SP, (FCC_NUM + FP_BASE_INDEX) * RSIZE +1: + or A0, SP, ZERO + bl CommonExceptionEntry + /*disable interrupt*/ + li.d T0, (1 << 2) + csrxchg ZERO, T0, LOONGARCH_CSR_CRMD + + ld.d T0, SP, (LOONGARCH_CSR_PRMD + BASE_NUM) * RSIZE + csrwr T0, LOONGARCH_CSR_PRMD + ld.d T0, SP, (LOONGARCH_CSR_ECFG + BASE_NUM) * RSIZE + csrwr T0, LOONGARCH_CSR_ECFG + ld.d T0, SP, (LOONGARCH_CSR_EPC + BASE_NUM) * RSIZE + csrwr T0, LOONGARCH_CSR_EPC + + ld.d T0, SP, (LOONGARCH_CSR_EUEN + BASE_NUM) * RSIZE + ori T1, ZERO, CSR_EUEN_FPEN + and T2, T0, T1 + beqz T2, 2f + + /* + * check previous FP state + * restore FP contect if FP enabled + */ + fld.d $f0, SP, (FP0_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f1, SP, (FP1_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f2, SP, (FP2_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f3, SP, (FP3_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f4, SP, (FP4_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f5, SP, (FP5_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f6, SP, (FP6_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f7, SP, (FP7_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f8, SP, (FP8_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f9, SP, (FP9_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f10, SP, (FP10_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f11, SP, (FP11_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f12, SP, (FP12_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f13, SP, (FP13_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f14, SP, (FP14_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f15, SP, (FP15_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f16, SP, (FP16_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f17, SP, (FP17_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f18, SP, (FP18_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f19, SP, (FP19_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f20, SP, (FP20_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f21, SP, (FP21_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f22, SP, (FP22_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f23, SP, (FP23_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f24, SP, (FP24_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f25, SP, (FP25_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f26, SP, (FP26_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f27, SP, (FP27_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f28, SP, (FP28_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f29, SP, (FP29_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f30, SP, (FP30_NUM + FP_BASE_INDEX) * RSIZE + fld.d $f31, SP, (FP31_NUM + FP_BASE_INDEX) * RSIZE + + ld.d T0, SP, (FCSR_NUM + FP_BASE_INDEX) * RSIZE + movgr2fcsr FCSR0, T0 + ld.d T0, SP, (FCC_NUM + FP_BASE_INDEX) * RSIZE + bstrpick.d T1, T0, 7, 0 + movgr2cf $fcc0, T1 + bstrpick.d T1, T0, 15, 8 + movgr2cf $fcc1, T1 + bstrpick.d T1, T0, 23, 16 + movgr2cf $fcc2, T1 + bstrpick.d T1, T0, 31, 24 + movgr2cf $fcc3, T1 + bstrpick.d T1, T0, 39, 32 + movgr2cf $fcc4, T1 + bstrpick.d T1, T0, 47, 40 + movgr2cf $fcc5, T1 + bstrpick.d T1, T0, 55, 48 + movgr2cf $fcc6, T1 + bstrpick.d T1, T0, 63, 56 + movgr2cf $fcc7, T1 +2: + ld.d RA, SP, RA_NUM * RSIZE + ld.d GP, SP, GP_NUM * RSIZE + ld.d A0, SP, A0_NUM * RSIZE + ld.d A1, SP, A1_NUM * RSIZE + ld.d A2, SP, A2_NUM * RSIZE + ld.d A3, SP, A3_NUM * RSIZE + ld.d A4, SP, A4_NUM * RSIZE + ld.d A5, SP, A5_NUM * RSIZE + ld.d A6, SP, A6_NUM * RSIZE + ld.d A7, SP, A7_NUM * RSIZE + ld.d T0, SP, T0_NUM * RSIZE + ld.d T1, SP, T1_NUM * RSIZE + ld.d T2, SP, T2_NUM * RSIZE + ld.d T3, SP, T3_NUM * RSIZE + ld.d T4, SP, T4_NUM * RSIZE + ld.d T5, SP, T5_NUM * RSIZE + ld.d T6, SP, T6_NUM * RSIZE + ld.d T7, SP, T7_NUM * RSIZE + ld.d T8, SP, T8_NUM * RSIZE + ld.d TP, SP, TP_NUM * RSIZE + ld.d FP, SP, FP_NUM * RSIZE + ld.d S0, SP, S0_NUM * RSIZE + ld.d S1, SP, S1_NUM * RSIZE + ld.d S2, SP, S2_NUM * RSIZE + ld.d S3, SP, S3_NUM * RSIZE + ld.d S4, SP, S4_NUM * RSIZE + ld.d S5, SP, S5_NUM * RSIZE + ld.d S6, SP, S6_NUM * RSIZE + ld.d S7, SP, S7_NUM * RSIZE + ld.d S8, SP, S8_NUM * RSIZE + + ld.d SP, SP, SP_NUM * RSIZE + ertn + +/* + Exception trampoline copied down to RAM after initialization. + */ +ASM_FUNC(LoongArchException) + csrwr T0, LOONGARCH_CSR_KS0 + csrwr SP, LOONGARCH_CSR_KS1 + pcaddi T0, 0 + ld.d T0, T0, 16 + jirl ZERO, T0, 0 + nop +1: + .quad Exception_handler +.globl LoongArchExceptionEnd +LoongArchExceptionEnd: + +/* + Set Exception Base Address. + */ +ASM_FUNC(SetEbase) + /* + * clear Vint cofigure + * all exceptions share the same interrupt entry + */ + csrrd T0, LOONGARCH_CSR_ECFG + li.d T1, ~0x70000 + and T0, T0, T1 + csrwr T0, LOONGARCH_CSR_ECFG + + /*set ebase*/ + csrwr A0, LOONGARCH_CSR_EBASE + jirl ZERO, RA, 0 --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93890): https://edk2.groups.io/g/devel/message/93890 Mute This Topic: https://groups.io/mt/93715808/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93902+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93902+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299419; cv=none; d=zohomail.com; s=zohoarc; b=IOcb/ecxPZF97XYZnv0UjdQMdaJa+4EeUe4D9bLzKMn8coiz3OY4JIExNftztay1tIG8Wf4k/ohLe+YlpFanoz3uUC2Y/7OGb+/q81etYyqXHRRlLDDgN2z9kSh7t+igaQNsB/Xbsdl3Vhth5lNC7tSvwkBHZ+5ZDwILPa9l118= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299419; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=xi4rhvFA68eeNaz2DdCPrTKk+7gFxkugqVyrEbW5qPY=; b=lqJr+Yjsbtx49yao694cR/We0IQC7XlI8ZWDKibkK4axlonBQUCsblCpnE5Qs2FbeIwOG3yU6cgZdiSbAA/+kXABots3T+SArJvk5pvSe86peHIi5w5eAQzQgzN5BvJT4/XDj5ucrFHbQiFvlKLsEa7zWMlMUV/pATLlUd8C+C8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93902+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299419891225.03377236450376; Thu, 15 Sep 2022 20:36:59 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 5ENvYY1788612x8zHEehTcqd; Thu, 15 Sep 2022 20:36:59 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web12.2043.1663299410914260339 for ; Thu, 15 Sep 2022 20:36:59 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S11; Fri, 16 Sep 2022 11:36:40 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 09/16] Platform/Loongson: Add PciCpuIoDxe driver. Date: Fri, 16 Sep 2022 11:36:26 +0800 Message-Id: <58618c8236a7a0959776aa025c3fe376a6ccba92.1663298005.git.lixianglai@loongson.cn> In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S11 X-Coremail-Antispam: 1UD129KBjvAXoWfur1rKrWfZr18CFWruF17ZFb_yoW5Zr48Wo W093yIvws8tw1rGrZ8C3sYya17XFnrWFsaqF4rAF1UWa1qqrn5Ka4rX3WUGryrt3yDuFWD Ja4UX3yxJrsYqa4fn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: Yzv2ohOEMUGK6sfeaxhq4y7Tx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299419; bh=LhaiTjB1brqKyCXLIRDaPFWutl1NTFC0AStyz88Z8hs=; h=Cc:Date:From:Reply-To:Subject:To; b=mGyiGtcR63nu8sOmWKD93b8LXGmH/trwsrnDlevESNEnVBAv2liFRL+0pP1VGNL3a2C TzxgI6H73Wall5NuEFTCyDMyxfCgCROnEIhT3Ryl+jVU6Q1VPdHsS5vFIHmQt5xMBnH6+ ur9sX9E2PmwN40+rTbHGDw1V1Wx9GpCRHGY= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299420386100001 Content-Type: text/plain; charset="utf-8" Add PCI CpuIo protocol.there is no fix translation offset between I/O port accesses and MMIO accesses. Add PciCpuIo2Dxe driver to implement EFI_CPU_IO2_PROTOCOL to add the translation for IO access. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c | 548 ++++++++++++++++++ .../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.h | 219 +++++++ .../Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf | 40 ++ 3 files changed, 807 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe= /PciCpuIo2Dxe.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe= /PciCpuIo2Dxe.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe= /PciCpuIo2Dxe.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo= 2Dxe.c new file mode 100644 index 0000000000..f5154eea7a --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.c @@ -0,0 +1,548 @@ +/** @file + Produces the CPU I/O 2 Protocol. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include +#include +#include "PciCpuIo2Dxe.h" + +// +// Handle for the CPU I/O 2 Protocol +// +STATIC EFI_HANDLE mHandle =3D NULL; + +// +// Lookup table for increment values based on transfer widths +// +STATIC CONST UINT8 mInStride[] =3D { + 1, // EfiCpuIoWidthUint8 + 2, // EfiCpuIoWidthUint16 + 4, // EfiCpuIoWidthUint32 + 8, // EfiCpuIoWidthUint64 + 0, // EfiCpuIoWidthFifoUint8 + 0, // EfiCpuIoWidthFifoUint16 + 0, // EfiCpuIoWidthFifoUint32 + 0, // EfiCpuIoWidthFifoUint64 + 1, // EfiCpuIoWidthFillUint8 + 2, // EfiCpuIoWidthFillUint16 + 4, // EfiCpuIoWidthFillUint32 + 8 // EfiCpuIoWidthFillUint64 +}; + +// +// Lookup table for increment values based on transfer widths +// +STATIC CONST UINT8 mOutStride[] =3D { + 1, // EfiCpuIoWidthUint8 + 2, // EfiCpuIoWidthUint16 + 4, // EfiCpuIoWidthUint32 + 8, // EfiCpuIoWidthUint64 + 1, // EfiCpuIoWidthFifoUint8 + 2, // EfiCpuIoWidthFifoUint16 + 4, // EfiCpuIoWidthFifoUint32 + 8, // EfiCpuIoWidthFifoUint64 + 0, // EfiCpuIoWidthFillUint8 + 0, // EfiCpuIoWidthFillUint16 + 0, // EfiCpuIoWidthFillUint32 + 0 // EfiCpuIoWidthFillUint64 +}; + +/** + Check parameters to a CPU I/O 2 Protocol service request. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port= operation. + @param[in] Width Signifies the width of the I/O or Memory opera= tion. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The n= umber of + bytes moved is Width size * Count, starting at= Address. + @param[in] Buffer For read operations, the destination buffer to= store the results. + For write operations, the source buffer from w= hich to write data. + + @retval EFI_SUCCESS The parameters for this request pass the = checks. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +CpuIoCheckParameter ( + IN BOOLEAN MmioOperation, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT64 MaxCount; + UINT64 Limit; + + // + // Check to see if Buffer is NULL + // + if (Buffer =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if Width is in the valid range + // + if ((UINT32)Width >=3D EfiCpuIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + // + // For FIFO type, the target address won't increase during the access, + // so treat Count as 1 + // + if ((Width >=3D EfiCpuIoWidthFifoUint8) + && (Width <=3D EfiCpuIoWidthFifoUint64)) + { + Count =3D 1; + } + + // + // Check to see if Width is in the valid range for I/O Port operations + // + Width =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + if ((!MmioOperation) + && (Width =3D=3D EfiCpuIoWidthUint64)) + { + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if Address is aligned + // + if ((Address & (UINT64) (mInStride[Width] - 1)) !=3D 0) { + return EFI_UNSUPPORTED; + } + + // + // Check to see if any address associated with this transfer exceeds the= maximum + // allowed address. The maximum address implied by the parameters passe= d in is + // Address + Size * Count. If the following condition is met, then the = transfer + // is not supported. + // + // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_POR= T_ADDRESS) + 1 + // + // Since MAX_ADDRESS can be the maximum integer value supported by the C= PU and Count + // can also be the maximum integer value supported by the CPU, this range + // check must be adjusted to avoid all overflow conditions. + // + // The following form of the range check is equivalent but assumes that + // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1). + // + Limit =3D (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS); + if (Count =3D=3D 0) { + if (Address > Limit) { + return EFI_UNSUPPORTED; + } + } else { + MaxCount =3D RShiftU64 (Limit, Width); + if (MaxCount < (Count - 1)) { + return EFI_UNSUPPORTED; + } + if (Address > LShiftU64 (MaxCount - Count + 1, Width)) { + return EFI_UNSUPPORTED; + } + } + + // + // Check to see if Buffer is aligned + // + if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != =3D 0) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Reads memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[out] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuMemoryServiceRead ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + Status =3D CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + *Uint8Buffer =3D MmioRead8 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + *((UINT16 *)Uint8Buffer) =3D MmioRead16 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + *((UINT32 *)Uint8Buffer) =3D MmioRead32 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint64) { + *((UINT64 *)Uint8Buffer) =3D MmioRead64 ((UINTN)Address); + } + } + return EFI_SUCCESS; +} + +/** + Writes memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[in] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuMemoryServiceWrite ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status =3D CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + MmioWrite8 ((UINTN)Address, *Uint8Buffer); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint64) { + MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); + } + } + return EFI_SUCCESS; +} + +/** + Reads I/O registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[out] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuIoServiceRead ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status =3D CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + Address +=3D PcdGet64 (PcdPciIoTranslation); + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + *Uint8Buffer =3D MmioRead8 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + *((UINT16 *)Uint8Buffer) =3D MmioRead16 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + *((UINT32 *)Uint8Buffer) =3D MmioRead32 ((UINTN)Address); + } + } + + return EFI_SUCCESS; +} + +/** + Write I/O registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[in] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuIoServiceWrite ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + // + // Make sure the parameters are valid + // + Status =3D CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + Address +=3D PcdGet64 (PcdPciIoTranslation); + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); + + for (Uint8Buffer =3D (UINT8 *)Buffer; Count > 0; Address +=3D InStride, = Uint8Buffer +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + MmioWrite8 ((UINTN)Address, *Uint8Buffer); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + } + } + + return EFI_SUCCESS; +} + +// +// CPU I/O 2 Protocol instance +// +STATIC EFI_CPU_IO2_PROTOCOL mCpuIo2 =3D { + { + CpuMemoryServiceRead, + CpuMemoryServiceWrite + }, + { + CpuIoServiceRead, + CpuIoServiceWrite + } +}; + + +/** + The user Entry Point for module CpuIo2Dxe. The user code starts with thi= s function. + + @param[in] ImageHandle The firmware allocated handle for the EFI imag= e. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry po= int. + +**/ +EFI_STATUS +EFIAPI +PciCpuIo2Initialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid); + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiCpuIo2ProtocolGuid, &mCpuIo2, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.h b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo= 2Dxe.h new file mode 100644 index 0000000000..a3f8cf7cbb --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.h @@ -0,0 +1,219 @@ +/** @file + Internal include file for the CPU I/O 2 Protocol. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef PCI_CPU_IO2_DXE_H_ +#define PCI_CPU_IO2_DXE_H_ + +//#include +// +//#include +// +//#include +//#include +//#include +//#include + +#define MAX_IO_PORT_ADDRESS 0xFFFF + +/** + Reads memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[out] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuMemoryServiceRead ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Writes memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[in] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuMemoryServiceWrite ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Reads I/O registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[out] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuIoServiceRead ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Write I/O registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[in] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +EFI_STATUS +EFIAPI +CpuIoServiceWrite ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ); + +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.inf b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpu= Io2Dxe.inf new file mode 100644 index 0000000000..9fb7160ae7 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.= inf @@ -0,0 +1,40 @@ +## @file +# Produces the CPU I/O 2 Protocol by using the services of the I/O Librar= y. +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PciCpuIo2Dxe + FILE_GUID =3D 168D1A6E-F4A5-448A-9E95-795661BB3067 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D PciCpuIo2Initialize + +[Sources] + PciCpuIo2Dxe.c + +[Packages] + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + BaseLib + DebugLib + IoLib + PcdLib + UefiBootServicesTableLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation + +[Protocols] + gEfiCpuIo2ProtocolGuid ## PRODUCES + +[Depex] + TRUE --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93902): https://edk2.groups.io/g/devel/message/93902 Mute This Topic: https://groups.io/mt/93715821/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93893+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93893+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299405; cv=none; d=zohomail.com; s=zohoarc; b=J06p3Q/gsDLjRPPKow8sIHwZj5H0sWZpS95txMN8A39HlVIcpy05gILmPtAQVQt4FMPNkK65fiHiCNGnS/eUZvLP+pV0CbZMHLJBioC/Ecd+wLN1Q5lT7diEV4drHsQmfVOZZ3gL4mGQrfj+OUoSopTj6vrEwnq3kp31IQ85IPM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299405; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=Brc8duHGIszNsM4HSO/gfr+SIDWZvoKtmNt/etTqAVU=; b=af/Fco9Exn6XNwxUumgICWwaHwYa7P2HGiiVWWqxIyEqv+NH86uwa7JBSi3x4PSTmANpkV83CJ+udQt/dd0tUAcqcxqrx09g7jhQfOc5FdWnL78stqAnirB7QaoK0dRnWXpxq07n8A/tR1N6pK4tEPDPAK2uKP3ABAPxqwgbMss= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93893+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299405697920.6975349933517; Thu, 15 Sep 2022 20:36:45 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id VnIlYY1788612xmuZtGuOgHY; Thu, 15 Sep 2022 20:36:45 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web12.2042.1663299403086793105 for ; Thu, 15 Sep 2022 20:36:43 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S12; Fri, 16 Sep 2022 11:36:41 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 10/16] Platform/Loongson: Add timer Dxe driver. Date: Fri, 16 Sep 2022 11:36:27 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S12 X-Coremail-Antispam: 1UD129KBjvAXoWfKryrCr1kCF43GFWUCw1rJFb_yoW8ZF1xuo W0ka9Fvw48Gr18Xa98JFyxJ3W2qFn5uw4YqrsYgFykAFnYyw15Kr9FvFy5Kw1fZrW8GFsr A34xWa4kJFZxX3Z5n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: 1zomEJURC5WE1obsgbi1SRWyx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299405; bh=YdYszSIZyt0JxoX31e80ESTbVNSmSCEMBoknuQjQKuY=; h=Cc:Date:From:Reply-To:Subject:To; b=TIBZhUe4IZaZtrfVD1ouOgCKPvDVkNqh/hbESd4u8jYxEIun8P5qG7uHhRV18RUXI2j jK8bBv6FR7nC3YQixJZEYAjSt/YZ/qq6Zp6inqsDDVLZK3nC7QS4Nu8HqdqlE6FfexaiK LnIORDpqt5GXbak71ShlzlJbiUWGU8RJ3TY= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299406274100011 Content-Type: text/plain; charset="utf-8" This driver produces Timer Architectural Protocol, Registers a timer interrupt and initializes the timer. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../Drivers/StableTimerDxe/Timer.c | 405 ++++++++++++++++++ .../Drivers/StableTimerDxe/Timer.h | 165 +++++++ .../Drivers/StableTimerDxe/TimerDxe.inf | 40 ++ 3 files changed, 610 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/Timer.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/Timer.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/TimerDxe.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= r.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.c new file mode 100644 index 0000000000..29e10566b5 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.c @@ -0,0 +1,405 @@ +/** @file + Timer Architectural Protocol as defined in the DXE CIS + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include "Library/Cpu.h" +#include +#include +#include "Timer.h" +#include +#include + +// +// The handle onto which the Timer Architectural Protocol will be installed +// +EFI_HANDLE mTimerHandle =3D NULL; +EFI_EVENT EfiExitBootServicesEvent =3D (EFI_EVENT)NULL; + +// +// The Timer Architectural Protocol that this driver produces +// +EFI_TIMER_ARCH_PROTOCOL mTimer =3D { + TimerDriverRegisterHandler, + TimerDriverSetTimerPeriod, + TimerDriverGetTimerPeriod, + TimerDriverGenerateSoftInterrupt +}; + +// +// Pointer to the CPU Architectural Protocol instance +// +EFI_CPU_ARCH_PROTOCOL *mCpu; + +// +// The notification function to call on every timer interrupt. +// A bug in the compiler prevents us from initializing this here. +// +EFI_TIMER_NOTIFY mTimerNotifyFunction; + +// +// The current period of the timer interrupt +// +volatile UINT64 mTimerPeriod =3D 0; +volatile UINT64 mTimerTicks =3D 0; + +// +// Const frequence in Hz +// +extern UINT32 StableTimerFreq; + +/** + Sets the counter value for timer. + + @param Count The 16-bit counter value to program into stable timer. + + @retval VOID +**/ +VOID +SetPitCount ( + IN UINT64 Count + ) +{ + if (Count <=3D 4) { + return; + } + + Count &=3D LOONGARCH_CSR_TMCFG_TIMEVAL; + Count |=3D LOONGARCH_CSR_TMCFG_EN | LOONGARCH_CSR_TMCFG_PERIOD; + LOONGARCH_CSR_WRITEQ (Count, LOONGARCH_CSR_TMCFG); +} + +/** + Timer Interrupt Handler. + + @param InterruptType The type of interrupt that occurred + @param SystemContext A pointer to the system context when the interru= pt occurred + + @retval VOID +**/ +VOID +EFIAPI +TimerInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_TPL OriginalTPL; + + OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + // + // Clear interrupt. + // + LOONGARCH_CSR_WRITEQ (0x1, LOONGARCH_CSR_TINTCLR); + + if (mTimerNotifyFunction !=3D NULL) { + // + // @bug : This does not handle missed timer interrupts + // + mTimerNotifyFunction (mTimerPeriod); + } + + gBS->RestoreTPL (OriginalTPL); +} + +/** + + This function registers the handler NotifyFunction so it is called every= time + the timer interrupt fires. It also passes the amount of time since the = last + handler call to the NotifyFunction. If NotifyFunction is NULL, then the + handler is unregistered. If the handler is registered, then EFI_SUCCESS= is + returned. If the CPU does not support registering a timer interrupt han= dler, + then EFI_UNSUPPORTED is returned. If an attempt is made to register a h= andler + when a handler is already registered, then EFI_ALREADY_STARTED is return= ed. + If an attempt is made to unregister a handler when a handler is not regi= stered, + then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to + register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ER= ROR + is returned. + + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param NotifyFunction The function to call when a timer interrupt fire= s. This + function executes at TPL_HIGH_LEVEL. The DXE Co= re will + register a handler for the timer interrupt, so i= t can know + how much time has passed. This information is u= sed to + signal timer based events. NULL will unregister= the handler. + + @retval EFI_SUCCESS The timer handler was registered. + @retval EFI_UNSUPPORTED The platform does not support time= r interrupts. + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a = handler is already + registered. + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a hand= ler was not + previously registered. + @retval EFI_DEVICE_ERROR The timer handler could not be reg= istered. + +**/ +EFI_STATUS +EFIAPI +TimerDriverRegisterHandler ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction + ) +{ + // + // Check for invalid parameters + // + if ((NotifyFunction =3D=3D NULL) + && (mTimerNotifyFunction =3D=3D NULL)) + { + return EFI_INVALID_PARAMETER; + } + + if ((NotifyFunction !=3D NULL) + && mTimerNotifyFunction !=3D NULL) + { + return EFI_ALREADY_STARTED; + } + + mTimerNotifyFunction =3D NotifyFunction; + + return EFI_SUCCESS; +} + +/** + + This function adjusts the period of timer interrupts to the value specif= ied + by TimerPeriod. If the timer period is updated, then the selected timer + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. = If + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. + If an error occurs while attempting to update the timer period, then the + timer hardware will be put back in its state prior to this call, and + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer inter= rupt + is disabled. This is not the same as disabling the CPU's interrupts. + Instead, it must either turn off the timer hardware, or it must adjust t= he + interrupt controller so that a CPU interrupt is not generated when the t= imer + interrupt fires. + + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod The rate to program the timer interrupt in 100 nS= units. If + the timer hardware is not programmable, then EFI_= UNSUPPORTED is + returned. If the timer is programmable, then the= timer period + will be rounded up to the nearest timer period th= at is supported + by the timer hardware. If TimerPeriod is set to = 0, then the + timer interrupts will be disabled. + + @retval EFI_SUCCESS The timer period was changed. + @retval EFI_UNSUPPORTED The platform cannot change the period o= f the timer interrupt. + @retval EFI_DEVICE_ERROR The timer period could not be changed d= ue to a device error. + +**/ +EFI_STATUS +EFIAPI +TimerDriverSetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +{ + UINT64 TimerCount; + + if (TimerPeriod =3D=3D 0) { + // + // Disable timer interrupt for a TimerPeriod of 0 + // + mCpu->DisableInterrupt (mCpu); + } else { + + TimerCount =3D TimerPeriod * StableTimerFreq / 10000000ULL; + + if (TimerCount >=3D BIT48) { + TimerCount =3D 0; + } + + // + // Program the stable timer with the new count value + // + mTimerTicks =3D TimerCount; + SetPitCount (TimerCount); + + // + // Enable timer interrupt + // + mCpu->EnableInterrupt (mCpu); + } + + // + // Save the new timer period + // + mTimerPeriod =3D TimerPeriod; + + return EFI_SUCCESS; +} + +/** + + This function retrieves the period of timer interrupts in 100 ns units, + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPer= iod + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 = is + returned, then the timer is currently disabled. + + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod A pointer to the timer period to retrieve in 100 = ns units. If + 0 is returned, then the timer is currently disabl= ed. + + @retval EFI_SUCCESS The timer period was returned in TimerPer= iod. + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. + +**/ +EFI_STATUS +EFIAPI +TimerDriverGetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ) +{ + if (TimerPeriod =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + *TimerPeriod =3D mTimerPeriod; + + return EFI_SUCCESS; +} + +/** + Disable the timer +**/ + +/** + Disable the timer + DXE Core will disable the timer after all the event handlers have run. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +ExitBootServicesEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + /* + * Disable timer interrupt when exiting boot service + */ + LOONGARCH_CSR_WRITEQ (0, LOONGARCH_CSR_TMCFG); +} + +/** + + This function generates a soft timer interrupt. If the platform does not= support soft + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCE= SS is returned. + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.Reg= isterHandler () + service, then a soft timer interrupt will be generated. If the timer int= errupt is + enabled when this service is called, then the registered handler will be= invoked. The + registered handler should not be able to distinguish a hardware-generate= d timer + interrupt from a software-generated timer interrupt. + + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS The soft timer interrupt was generated. + @retval EFI_UNSUPPORTED The platform does not support the generation o= f soft timer interrupts. + +**/ +EFI_STATUS +EFIAPI +TimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Initialize the Timer Architectural Protocol driver + + @param ImageHandle ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Timer Architectural Protocol created + @retval EFI_OUT_OF_RESOURCES Not enough resources available to initial= ize driver. + @retval EFI_DEVICE_ERROR A device error occurred attempting to ini= tialize the driver. + +**/ +EFI_STATUS +EFIAPI +StableTimerDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT32 TimerVector; + + // + // Initialize the pointer to our notify function. + // + mTimerNotifyFunction =3D NULL; + + // + // Make sure the Timer Architectural Protocol is not already installed i= n the system + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid); + + // + // Find the CPU architectural protocol. + // + Status =3D gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **= ) &mCpu); + ASSERT_EFI_ERROR (Status); + + // + // Force the timer to be disabled + // + Status =3D TimerDriverSetTimerPeriod (&mTimer, 0); + ASSERT_EFI_ERROR (Status); + + // + // Calculate const frequence + // + StableTimerFreq =3D CalcConstFreq (); + DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3DStable timer freq = %d Hz=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n", StableTimerFreq)); + + // + // Install interrupt handler for Stable Timer #0 (ISA IRQ0) + // + TimerVector =3D 0; + Status =3D mCpu->RegisterInterruptHandler (mCpu, TimerVector, TimerInter= ruptHandler); + ASSERT_EFI_ERROR (Status); + + // + // Enable TI local timer interrupt + // + CpuSetIP (1 << 11); + + // + // Force the timer to be enabled at its default period + // + Status =3D TimerDriverSetTimerPeriod (&mTimer, DEFAULT_TIMER_TICK_DURATI= ON); + ASSERT_EFI_ERROR (Status); + + // + // Install the Timer Architectural Protocol onto a new handle + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &mTimerHandle, + &gEfiTimerArchProtocolGuid, &mTimer, + NULL + ); + + ASSERT_EFI_ERROR (Status); + + // Register for an ExitBootServicesEvent + Status =3D gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, = ExitBootServicesEvent, NULL, + &EfiExitBootServicesEvent); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= r.h b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.h new file mode 100644 index 0000000000..7fe5c9c179 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.h @@ -0,0 +1,165 @@ +/** @file + Private data structures + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef TIMER_H_ +#define TIMER_H_ + +#include + + +#define DEFAULT_TIMER_TICK_DURATION 100000 //10ms =3D 100000 100 ns units +#define SR_IP7 (1 << 15) +// +// Function Prototypes +// +extern UINT32 EFIAPI CpuGetCompare(VOID); +extern VOID EFIAPI CpuSetCompare(IN UINT32 val); +extern VOID EFIAPI CpuSetIP(IN UINT32 val); +extern VOID EFIAPI ClearC0Cause(IN UINT32 val); +extern VOID EFIAPI ClearC0Status(IN UINT32 val); +/** + Initialize the Timer Architectural Protocol driver + + @param ImageHandle ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Timer Architectural Protocol created + @retval EFI_OUT_OF_RESOURCES Not enough resources available to initial= ize driver. + @retval EFI_DEVICE_ERROR A device error occurred attempting to ini= tialize the driver. + +**/ +EFI_STATUS +EFIAPI +TimerDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +/** + + This function adjusts the period of timer interrupts to the value specif= ied + by TimerPeriod. If the timer period is updated, then the selected timer + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. = If + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. + If an error occurs while attempting to update the timer period, then the + timer hardware will be put back in its state prior to this call, and + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer inter= rupt + is disabled. This is not the same as disabling the CPU's interrupts. + Instead, it must either turn off the timer hardware, or it must adjust t= he + interrupt controller so that a CPU interrupt is not generated when the t= imer + interrupt fires. + + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param NotifyFunction The rate to program the timer interrupt in 100 nS= units. If + the timer hardware is not programmable, then EFI_= UNSUPPORTED is + returned. If the timer is programmable, then the= timer period + will be rounded up to the nearest timer period th= at is supported + by the timer hardware. If TimerPeriod is set to = 0, then the + timer interrupts will be disabled. + + @retval EFI_SUCCESS The timer period was changed. + @retval EFI_UNSUPPORTED The platform cannot change the period o= f the timer interrupt. + @retval EFI_DEVICE_ERROR The timer period could not be changed d= ue to a device error. + +**/ +EFI_STATUS +EFIAPI +TimerDriverRegisterHandler ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction + ) +; + +/** + + This function adjusts the period of timer interrupts to the value specif= ied + by TimerPeriod. If the timer period is updated, then the selected timer + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. = If + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. + If an error occurs while attempting to update the timer period, then the + timer hardware will be put back in its state prior to this call, and + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer inter= rupt + is disabled. This is not the same as disabling the CPU's interrupts. + Instead, it must either turn off the timer hardware, or it must adjust t= he + interrupt controller so that a CPU interrupt is not generated when the t= imer + interrupt fires. + + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod The rate to program the timer interrupt in 100 nS= units. If + the timer hardware is not programmable, then EFI_= UNSUPPORTED is + returned. If the timer is programmable, then the= timer period + will be rounded up to the nearest timer period th= at is supported + by the timer hardware. If TimerPeriod is set to = 0, then the + timer interrupts will be disabled. + + @retval EFI_SUCCESS The timer period was changed. + @retval EFI_UNSUPPORTED The platform cannot change the period o= f the timer interrupt. + @retval EFI_DEVICE_ERROR The timer period could not be changed d= ue to a device error. + +**/ +EFI_STATUS +EFIAPI +TimerDriverSetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +; + +/** + + This function retrieves the period of timer interrupts in 100 ns units, + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPer= iod + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 = is + returned, then the timer is currently disabled. + + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod A pointer to the timer period to retrieve in 100 = ns units. If + 0 is returned, then the timer is currently disabl= ed. + + @retval EFI_SUCCESS The timer period was returned in TimerPer= iod. + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. + +**/ +EFI_STATUS +EFIAPI +TimerDriverGetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ) +; + +/** + + This function generates a soft timer interrupt. If the platform does not= support soft + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCE= SS is returned. + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.Reg= isterHandler() + service, then a soft timer interrupt will be generated. If the timer int= errupt is + enabled when this service is called, then the registered handler will be= invoked. The + registered handler should not be able to distinguish a hardware-generate= d timer + interrupt from a software-generated timer interrupt. + + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS The soft timer interrupt was generated. + @retval EFI_UNSUPPORTED The platform does not support the generation o= f soft timer interrupts. + +**/ +EFI_STATUS +EFIAPI +TimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ) +; + +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= rDxe.inf b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/TimerD= xe.inf new file mode 100644 index 0000000000..10e6b9a85e --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/TimerDxe.inf @@ -0,0 +1,40 @@ +## @file +# Stable timer driver that provides Timer Arch protocol. +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D Timer + MODULE_UNI_FILE =3D Timer.uni + FILE_GUID =3D AEBE2648-47A9-40FA-83FD-06AA88443BB2 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + + ENTRY_POINT =3D StableTimerDriverInitialize + +[Packages] + MdePkg/MdePkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + +[LibraryClasses] + UefiBootServicesTableLib + BaseLib + DebugLib + UefiDriverEntryPoint + IoLib + TimerLib + +[Sources] + Timer.h + Timer.c + +[Protocols] + gEfiCpuArchProtocolGuid ## CONSUMES + gEfiTimerArchProtocolGuid ## PRODUCES + +[depex] + TRUE --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93893): https://edk2.groups.io/g/devel/message/93893 Mute This Topic: https://groups.io/mt/93715812/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93899+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93899+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299412; cv=none; d=zohomail.com; s=zohoarc; b=GR0Dj2S9NyiS1XCR+FkGWda7568A1CLSVK4fPMfy6gaipJfp8Zhjs5Kc/Auq/kwPkmU/2pDCyOo9GUbOBRJybLABxdwGcCVa5BkXDWYTh9xGMJkMXjM79eSyYqJfVpFRR9SBzwS9S7bqRnSmrjyS/DPvzJqVinOcUbIiaCFee+U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299412; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=VRLkw5W71D4XGr8YkNsyg9NliLTuPOjmW7fdYc0jHuY=; b=lPc1Q8OurZOteqkLyePL/xIA5gy5BV75qErgWRwxItZNc3OE9Bw/u5xnIQ2WAgUfGyqs0tYwTpDA0JoxW3hE/Y9wSiaJiBQrxLjKh/juHNMvDzmU58EoGkKdo8wVWa884GauQHxwkQAkIFCAxtz4mgoS1lrZup0JyZKie+2R0yo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93899+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299412809483.8180595131745; Thu, 15 Sep 2022 20:36:52 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id AdVbYY1788612xPLWKDQ9768; Thu, 15 Sep 2022 20:36:51 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web10.2141.1663299407763247368 for ; Thu, 15 Sep 2022 20:36:51 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S13; Fri, 16 Sep 2022 11:36:41 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 11/16] Platform/Loongson: Add RealTime Clock lib. Date: Fri, 16 Sep 2022 11:36:28 +0800 Message-Id: <8a07e97b5c993eb7eb4666c601f6968470ab3734.1663298005.git.lixianglai@loongson.cn> In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S13 X-Coremail-Antispam: 1UD129KBjvAXoW3Zr4xAFyfWr17JF1fXw43Jrb_yoW8Jr17Ao WxtFWSqw48Jr18uasa9rykCrWIgF9Iqa1fXr1FqFWjyan8Ar1UtFyUta42gryfArykAwsx Kr93A3ykJFWaqFW8n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: YQ5QDDUt1uk8cGceb7uPxRBsx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299411; bh=Xe5IpiTJODsJHjJwJF1nn5c7QEB2x97qZokaV1+2z50=; h=Cc:Date:From:Reply-To:Subject:To; b=cGD21rBNl1KBT0ddgUTOOE25hYvNtxbB0YXZ06mpgPSJxZKrRG0bd69gmcgVkdaaFZ2 wOImcTjTdhmhcGZApJFuMn8R7mWNCm6BjDibTqjz9C4vu4YxFq4ybgskcjkUFEvweoX/t nR7qU2Bi8NOS+VuNadA9EvoFU2J6e8AuSyY= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299414348100051 Content-Type: text/plain; charset="utf-8" This library provides interfaces such as real-time clock initialization to get time and setting time. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../LsRealTimeClockLib/LsRealTimeClock.h | 41 +++ .../LsRealTimeClockLib/LsRealTimeClockLib.c | 343 ++++++++++++++++++ .../LsRealTimeClockLib/LsRealTimeClockLib.inf | 41 +++ 3 files changed, 425 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeCl= ockLib/LsRealTimeClock.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeCl= ockLib/LsRealTimeClockLib.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeCl= ockLib/LsRealTimeClockLib.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/= LsRealTimeClock.h b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeCl= ockLib/LsRealTimeClock.h new file mode 100644 index 0000000000..c98881e5d0 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealT= imeClock.h @@ -0,0 +1,41 @@ +/** @file + Implement EFI RealTimeClock runtime services via RTC Lib. + + Copyright (c) 2021, Loongson Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#ifndef LS_REAL_TIME_CLOCK_H_ +#define LS_REAL_TIME_CLOCK_H_ + +#define TOY_WRITE0_REG 0x24 +#define TOY_WRITE1_REG 0x28 +#define TOY_READ0_REG 0x2c +#define TOY_READ1_REG 0x30 +#define RTC_CTRL_REG 0x40 + +/* TOY Enable bits */ +#define RTC_ENABLE_BIT (1UL << 13) +#define TOY_ENABLE_BIT (1UL << 11) +#define OSC_ENABLE_BIT (1UL << 8) + +/* + * shift bits and filed mask + */ +#define TOY_MON_MASK 0x3f +#define TOY_DAY_MASK 0x1f +#define TOY_HOUR_MASK 0x1f +#define TOY_MIN_MASK 0x3f +#define TOY_SEC_MASK 0x3f +#define TOY_MSEC_MASK 0xf + +#define TOY_MON_SHIFT 26 +#define TOY_DAY_SHIFT 21 +#define TOY_HOUR_SHIFT 16 +#define TOY_MIN_SHIFT 10 +#define TOY_SEC_SHIFT 4 + +#endif //__LS_REAL_TIME_CLOCK_H__ diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/= LsRealTimeClockLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTim= eClockLib/LsRealTimeClockLib.c new file mode 100644 index 0000000000..78420ddfab --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealT= imeClockLib.c @@ -0,0 +1,343 @@ +/** @file + Implement EFI RealTimeClock runtime services via RTC Lib. + + Copyright (c) 2021, Loongson Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "LsRealTimeClock.h" + +STATIC BOOLEAN mInitialized =3D FALSE; +STATIC EFI_EVENT mRtcVirtualAddrChangeEvent; +STATIC UINTN mRtcBase =3D 0X100d0100; +/* + Enable Real-time clock. + + @param VOID + + @retval VOID + */ +VOID +InitRtc ( + VOID + ) +{ + UINTN Val; + + if (!mInitialized) { + /* enable rtc */ + Val =3D MmioRead32 (mRtcBase + RTC_CTRL_REG); + Val |=3D TOY_ENABLE_BIT | OSC_ENABLE_BIT; + MmioWrite32 (mRtcBase + RTC_CTRL_REG, Val); + mInitialized =3D TRUE; + } +} + +/** + Returns the current time and date information, and the time-keeping capa= bilities + of the hardware platform. + + @param Time A pointer to storage to receive a snapsho= t of the current time. + @param Capabilities An optional pointer to a buffer to receiv= e the real time clock + device's capabilities. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The time could not be retrieved due to ha= rdware error. + @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an= authentication failure. + +**/ +EFI_STATUS +EFIAPI +LibGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +{ + UINT32 Val; + + // Ensure Time is a valid pointer + if (Time =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + InitRtc (); + Val =3D MmioRead32 (mRtcBase + TOY_READ1_REG); + Time->Year =3D Val + 1900; + + Val =3D MmioRead32 (mRtcBase + TOY_READ0_REG); + Time->Month =3D (Val >> TOY_MON_SHIFT) & TOY_MON_MASK; + Time->Day =3D (Val >> TOY_DAY_SHIFT) & TOY_DAY_MASK; + Time->Hour =3D (Val >> TOY_HOUR_SHIFT) & TOY_HOUR_MASK; + Time->Minute =3D (Val >> TOY_MIN_SHIFT) & TOY_MIN_MASK; + Time->Second =3D (Val >> TOY_SEC_SHIFT) & TOY_SEC_MASK; + Time->Nanosecond =3D 0; + return EFI_SUCCESS; +} + + +/** + Sets the current local time and date information. + + @param Time A pointer to the current time. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due due to hardw= are error. + +**/ +EFI_STATUS +EFIAPI +LibSetTime ( + IN EFI_TIME *Time + ) +{ + UINT32 Val; + + // Initialize the hardware if not already done + InitRtc (); + + Val =3D 0; + Val |=3D (Time->Second << TOY_SEC_SHIFT); + Val |=3D (Time->Minute << TOY_MIN_SHIFT); + Val |=3D (Time->Hour << TOY_HOUR_SHIFT); + Val |=3D (Time->Day << TOY_DAY_SHIFT); + Val |=3D (Time->Month << TOY_MON_SHIFT); + MmioWrite32 (mRtcBase + TOY_WRITE0_REG, Val); + + Val =3D Time->Year - 1900; + MmioWrite32 (mRtcBase + TOY_WRITE1_REG, Val); + return EFI_SUCCESS; +} + + +/** + Returns the current wakeup alarm clock setting. + + @param Enabled Indicates if the alarm is currently enable= d or disabled. + @param Pending Indicates if the alarm signal is pending a= nd requires acknowledgement. + @param Time The current alarm setting. + + @retval EFI_SUCCESS The alarm settings were returned. + @retval EFI_INVALID_PARAMETER Any parameter is NULL. + @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due= to a hardware error. + +**/ +EFI_STATUS +EFIAPI +LibGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +{ + // Not a required feature + return EFI_UNSUPPORTED; +} + + +/** + Sets the system wakeup alarm clock time. + + @param Enabled Enable or disable the wakeup alarm. + @param Time If Enable is TRUE, the time to set the wak= eup alarm for. + + @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm w= as enabled. If + Enable is FALSE, then the wakeup alarm was= disabled. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a = hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this pl= atform. + +**/ +EFI_STATUS +EFIAPI +LibSetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ) +{ + // Not a required feature + return EFI_UNSUPPORTED; +} + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +LibRtcVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Only needed if you are going to support the OS calling RTC functions = in virtual mode. + // You will need to call EfiConvertPointer (). To convert any stored phy= sical addresses + // to virtual address. After the OS transitions to calling in virtual mo= de, all future + // runtime calls will be made in virtual mode. + // + EfiConvertPointer (0x0, (VOID**)&mRtcBase); + return; +} + +/** Add the RTC controller address range to the memory map. + + @param [in] ImageHandle The handle to the image. + @param [in] RtcPageBase Base address of the RTC controller. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Flash device not found. +**/ +EFI_STATUS +KvmtoolRtcMapMemory ( + IN EFI_HANDLE ImageHandle, + IN EFI_PHYSICAL_ADDRESS RtcPageBase + ) +{ + EFI_STATUS Status; + + Status =3D gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + RtcPageBase, + EFI_PAGE_SIZE, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, "Failed to add memory space. Status =3D %r\n", + Status + )); + return Status; + } + + Status =3D gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeMemoryMappedIo, + 0, + EFI_PAGE_SIZE, + &RtcPageBase, + ImageHandle, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "Failed to allocate memory space. Status =3D %r\n", + Status + )); + gDS->RemoveMemorySpace ( + RtcPageBase, + EFI_PAGE_SIZE + ); + return Status; + } + + Status =3D gDS->SetMemorySpaceAttributes ( + RtcPageBase, + EFI_PAGE_SIZE, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "Failed to set memory attributes. Status =3D %r\n", + Status + )); + + gDS->FreeMemorySpace ( + RtcPageBase, + EFI_PAGE_SIZE + ); + + gDS->RemoveMemorySpace ( + RtcPageBase, + EFI_PAGE_SIZE + ); + } + + return Status; +} + +/** + This is the declaration of an EFI image entry point. This can be the ent= ry point to an application + written to this specification, an EFI boot service driver, or an EFI run= time driver. + + @param ImageHandle Handle that identifies the loaded image. + @param SystemTable System Table for this image. + + @retval EFI_SUCCESS The operation completed successfully. + +**/ +EFI_STATUS +EFIAPI +LibRtcInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + Status =3D KvmtoolRtcMapMemory (ImageHandle, (mRtcBase & ~EFI_PAGE_MASK)= ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "Failed to map memory for loongson 7A RTC. Status =3D %r\n", + Status + )); + return Status; + } + + // Setup the setters and getters + gRT->GetTime =3D LibGetTime; + gRT->SetTime =3D LibSetTime; + + // Install the protocol + Handle =3D NULL; + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiRealTimeClockArchProtocolGuid, NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Register for the virtual address change event + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + LibRtcVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mRtcVirtualAddrChangeEvent + ); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/= LsRealTimeClockLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealT= imeClockLib/LsRealTimeClockLib.inf new file mode 100644 index 0000000000..c985f7a727 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/LsRealTimeClockLib/LsRealT= imeClockLib.inf @@ -0,0 +1,41 @@ +## @file +# +# Copyright (c) 2021, Loongson Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D LsRealTimeClockLib + FILE_GUID =3D 9793a3da-1869-4fdf-88b1-c6484341f50b + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D RealTimeClockLib + +[Sources.common] + LsRealTimeClockLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + +[LibraryClasses] + IoLib + UefiLib + DebugLib + PcdLib + DxeServicesTableLib + UefiRuntimeLib + +[Guids] + gEfiEventVirtualAddressChangeGuid + +[Protocols] + gEfiRealTimeClockArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED + +[Depex] + TRUE + --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93899): https://edk2.groups.io/g/devel/message/93899 Mute This Topic: https://groups.io/mt/93715818/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93895+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93895+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299406; cv=none; d=zohomail.com; s=zohoarc; b=cbW6gJVOGcK0aUcUQB0BhTINpVdhNTAApe6sTIVXbi4IJP7iItoyK/yKSIDMQPEVz8HuOrNLjEO5x6o/G6Sj5bUM1QtD93VXVOMiTv7h3QqUfh4ZihK6U1Z/IegXIjMkGLi+yTywl5fjIWq6xDHvTgO244yobq4rU2838QOCFvU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299406; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=hRMRzB4tyGCf+Eo53gAmTmSjDH192ST/D9bLC9XaeXs=; b=byxNiTbVvgJDiUfkTOtIkLhUPs5gQmg4fjwGNZst4fs+w3lFBvPvmlIS3HbVCsjF3HpK+uqycgNRXIkfHzKTbMI0qQxa64k0VHHTm7TJ7Rdkuu3iAz8OXhDqvnpMSrsh1lxJaSXJpycTIyZJdOcl020PJPXg320q4nsfZC+MBNI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93895+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299406766319.6684967747409; Thu, 15 Sep 2022 20:36:46 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 6fDFYY1788612xSE04dp1WBc; Thu, 15 Sep 2022 20:36:46 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web08.2162.1663299404789404898 for ; Thu, 15 Sep 2022 20:36:45 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S14; Fri, 16 Sep 2022 11:36:42 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 12/16] Platform/Loongson: Add Platform Boot Manager Lib. Date: Fri, 16 Sep 2022 11:36:29 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S14 X-Coremail-Antispam: 1UD129KBjvAXoWfCw4rAr1rAFW3Zr4DZw1xAFb_yoW5Aw4DXo WIkFyxAw1kKr4xXas5Gr1kGa1xXF1qgwsxXr1vvF1UWa9Fg34Yga4DX3Z5K3sxAF1DZ3W7 Ja4fJa97AFWSvF95n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: TT0BqyCZU0bWX6u15yIPqRBax1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299406; bh=CI3D2Zx1a1X1N9xEMC3S9qxAvyoSvkLciwyPpmEKaM4=; h=Cc:Date:From:Reply-To:Subject:To; b=l89xysmmCoFWoLJXsy5veZtllWXghHYNUJ9FTyLfWndYDOvdMoTGG3e9fJcMIZjp8Fx 3wLpWnxAKmh4K2BqlFByPuUjjH/cM3MIvQVEdDafUKlG9wfMTKKwr6Ed6s/v/pFxYwLur qSekJyIjQ5jXgVvx4qJRoqJ+HpqOaQ2F78w= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299408326100026 Content-Type: text/plain; charset="utf-8" The Library provides Boot Manager interfaces. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../PlatformBootManagerLib/PlatformBm.c | 760 ++++++++++++++++++ .../PlatformBootManagerLib/PlatformBm.h | 112 +++ .../PlatformBootManagerLib.inf | 78 ++ .../PlatformBootManagerLib/QemuKernel.c | 81 ++ 4 files changed, 1031 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformBoot= ManagerLib/PlatformBm.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformBoot= ManagerLib/PlatformBm.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformBoot= ManagerLib/PlatformBootManagerLib.inf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformBoot= ManagerLib/QemuKernel.c diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManager= Lib/PlatformBm.c b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootM= anagerLib/PlatformBm.c new file mode 100644 index 0000000000..f58c43fa89 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pla= tformBm.c @@ -0,0 +1,760 @@ +/** @file + Implementation for PlatformBootManagerLib library class interfaces. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "PlatformBm.h" + +STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole =3D { + // + // VENDOR_DEVICE_PATH SerialDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_P= ATH) }, + SERIAL_DXE_FILE_GUID + }, + + // + // UART_DEVICE_PATH Uart + // + { + { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PAT= H) }, + 0, // Reserved + FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate + FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits + FixedPcdGet8 (PcdUartDefaultParity), // Parity + FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits + }, + + // + // VENDOR_DEFINED_DEVICE_PATH TermType + // + { + { + MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, + DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH) + } + // + // Guid to be filled in dynamically + // + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard =3D { + // + // USB_CLASS_DEVICE_PATH Keyboard + // + { + { + MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, + DP_NODE_LEN (USB_CLASS_DEVICE_PATH) + }, + 0xFFFF, // VendorId: any + 0xFFFF, // ProductId: any + 3, // DeviceClass: HID + 1, // DeviceSubClass: boot + 1 // DeviceProtocol: keyboard + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +/** + Locate all handles that carry the specified protocol, filter them with a + callback function, and pass each handle that passes the filter to another + callback. + + @param[in] ProtocolGuid The protocol to look for. + + @param[in] Filter The filter function to pass each handle to. If = this + parameter is NULL, then all handles are process= ed. + + @param[in] Process The callback function to pass each handle to th= at + clears the filter. +**/ +VOID +FilterAndProcess ( + IN EFI_GUID *ProtocolGuid, + IN FILTER_FUNCTION Filter OPTIONAL, + IN CALLBACK_FUNCTION Process + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Handles; + UINTN NoHandles; + UINTN Idx; + + Status =3D gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid, + NULL /* SearchKey */, &NoHandles, &Handles); + if (EFI_ERROR (Status)) { + // + // This is not an error, just an informative condition. + // + DEBUG ((DEBUG_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid, + Status)); + return; + } + + ASSERT (NoHandles > 0); + for (Idx =3D 0; Idx < NoHandles; ++Idx) { + CHAR16 *DevicePathText; + STATIC CHAR16 Fallback[] =3D L""; + + // + // The ConvertDevicePathToText () function handles NULL input transpar= ently. + // + DevicePathText =3D ConvertDevicePathToText ( + DevicePathFromHandle (Handles[Idx]), + FALSE, // DisplayOnly + FALSE // AllowShortcuts + ); + if (DevicePathText =3D=3D NULL) { + DevicePathText =3D Fallback; + } + + if ((Filter =3D=3D NULL) + || (Filter (Handles[Idx], DevicePathText))) + { + Process (Handles[Idx], DevicePathText); + } + + if (DevicePathText !=3D Fallback) { + FreePool (DevicePathText); + } + } + gBS->FreePool (Handles); +} + + +/** + This FILTER_FUNCTION checks if a handle corresponds to a PCI display dev= ice. + + @param Handle The handle to check + @param ReportText A pointer to a string at the time of the error. + + @retval TURE THe handle corresponds to a PCI display device. + @retval FALSE THe handle does not corresponds to a PCI display de= vice. +**/ +BOOLEAN +EFIAPI +IsPciDisplay ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + Status =3D gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid, + (VOID**)&PciIo); + if (EFI_ERROR (Status)) { + // + // This is not an error worth reporting. + // + return FALSE; + } + + Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */, + sizeof Pci / sizeof (UINT32), &Pci); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status)= ); + return FALSE; + } + + return IS_PCI_DISPLAY (&Pci); +} + + +/** + This CALLBACK_FUNCTION attempts to connect a handle non-recursively, ask= ing + the matching driver to produce all first-level child handles. + + @param Handle The handle to connect. + @param ReportText A pointer to a string at the time of the error. + + @retval VOID +**/ +VOID +EFIAPI +Connect ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + + Status =3D gBS->ConnectController ( + Handle, // ControllerHandle + NULL, // DriverImageHandle + NULL, // RemainingDevicePath -- produce all children + FALSE // Recursive + ); + DEBUG ((EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE, "%a: %s: %r\n", + __FUNCTION__, ReportText, Status)); +} + + +/** + This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the + handle, and adds it to ConOut and ErrOut. + + @param Handle The handle to retrieves. + @param ReportText A pointer to a string at the time of the error. + + @retval VOID +**/ +VOID +EFIAPI +AddOutput ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath =3D DevicePathFromHandle (Handle); + if (DevicePath =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a: %s: handle %p: device path not found\n", + __FUNCTION__, ReportText, Handle)); + return; + } + + Status =3D EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL= ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + Status =3D EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL= ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + DEBUG ((DEBUG_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTIO= N__, + ReportText)); +} +/** + Register the boot option. + + @param FileGuid File Guid. + @param Description Option descriptor. + @param Attributes Option Attributes. + + @retval VOID +**/ +VOID +PlatformRegisterFvBootOption ( + IN EFI_GUID *FileGuid, + IN CHAR16 *Description, + IN UINT32 Attributes + ) +{ + EFI_STATUS Status; + INTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status =3D gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + ASSERT_EFI_ERROR (Status); + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + DevicePath =3D DevicePathFromHandle (LoadedImage->DeviceHandle); + ASSERT (DevicePath !=3D NULL); + DevicePath =3D AppendDevicePathNode ( + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); + ASSERT (DevicePath !=3D NULL); + + Status =3D EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + FreePool (DevicePath); + + BootOptions =3D EfiBootManagerGetLoadOptions ( + &BootOptionCount, LoadOptionTypeBoot + ); + + OptionIndex =3D EfiBootManagerFindLoadOption ( + &NewOption, BootOptions, BootOptionCount + ); + + if (OptionIndex =3D=3D -1) { + Status =3D EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); + ASSERT_EFI_ERROR (Status); + } + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); +} + + +/** + Remove all MemoryMapped (...)/FvFile (...) and Fv (...)/FvFile (...) boo= t options + whose device paths do not resolve exactly to an FvFile in the system. + + This removes any boot options that point to binaries built into the firm= ware + and have become stale due to any of the following: + - FvMain's base address or size changed (historical), + - FvMain's FvNameGuid changed, + - the FILE_GUID of the pointed-to binary changed, + - the referenced binary is no longer built into the firmware. + + EfiBootManagerFindLoadOption () used in PlatformRegisterFvBootOption () = only + avoids exact duplicates. +**/ +VOID +RemoveStaleFvFileOptions ( + VOID + ) +{ + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + UINTN Index; + + BootOptions =3D EfiBootManagerGetLoadOptions (&BootOptionCount, + LoadOptionTypeBoot); + + for (Index =3D 0; Index < BootOptionCount; ++Index) { + EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode; + EFI_STATUS Status; + EFI_HANDLE FvHandle; + + // + // If the device path starts with neither MemoryMapped (...) nor Fv (.= ..), + // then keep the boot option. + // + Node1 =3D BootOptions[Index].FilePath; + if (!(DevicePathType (Node1) =3D=3D HARDWARE_DEVICE_PATH + && DevicePathSubType (Node1) =3D=3D HW_MEMMAP_DP) + && !(DevicePathType (Node1) =3D=3D MEDIA_DEVICE_PATH + && DevicePathSubType (Node1) =3D=3D MEDIA_PIWG_FW_VOL_DP)) + { + continue; + } + + // + // If the second device path node is not FvFile (...), then keep the b= oot + // option. + // + Node2 =3D NextDevicePathNode (Node1); + if ((DevicePathType (Node2) !=3D MEDIA_DEVICE_PATH) + || (DevicePathSubType (Node2) !=3D MEDIA_PIWG_FW_FILE_DP)) + { + continue; + } + + // + // Locate the Firmware Volume2 protocol instance that is denoted by the + // boot option. If this lookup fails (i.e., the boot option references= a + // firmware volume that doesn't exist), then we'll proceed to delete t= he + // boot option. + // + SearchNode =3D Node1; + Status =3D gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, + &SearchNode, &FvHandle); + + if (!EFI_ERROR (Status)) { + // + // The firmware volume was found; now let's see if it contains the F= vFile + // identified by GUID. + // + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode; + UINTN BufferSize; + EFI_FV_FILETYPE FoundType; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + UINT32 AuthenticationStatus; + + Status =3D gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2Protoc= olGuid, + (VOID **)&FvProtocol); + ASSERT_EFI_ERROR (Status); + + FvFileNode =3D (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2; + // + // Buffer=3D=3DNULL means we request metadata only: BufferSize, Foun= dType, + // FileAttributes. + // + Status =3D FvProtocol->ReadFile ( + FvProtocol, + &FvFileNode->FvFileName, // NameGuid + NULL, // Buffer + &BufferSize, + &FoundType, + &FileAttributes, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + // + // The FvFile was found. Keep the boot option. + // + continue; + } + } + + // + // Delete the boot option. + // + Status =3D EfiBootManagerDeleteLoadOptionVariable ( + BootOptions[Index].OptionNumber, LoadOptionTypeBoot); + DEBUG_CODE ( + CHAR16 *DevicePathString; + + DevicePathString =3D ConvertDevicePathToText (BootOptions[Index].Fil= ePath, + FALSE, FALSE); + DEBUG (( + EFI_ERROR (Status) ? EFI_D_WARN : DEBUG_VERBOSE, + "%a: removing stale Boot#%04x %s: %r\n", + __FUNCTION__, + (UINT32)BootOptions[Index].OptionNumber, + DevicePathString =3D=3D NULL ? L"" : DevicePathString, + Status + )); + if (DevicePathString !=3D NULL) { + FreePool (DevicePathString); + } + ); + } + + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); +} + +/** + Register the boot option And Keys. + + @param VOID + + @retval VOID +**/ +VOID +PlatformRegisterOptionsAndKeys ( + VOID + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Enter; + EFI_INPUT_KEY F2; + EFI_INPUT_KEY Esc; + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + + // + // Register ENTER as CONTINUE key + // + Enter.ScanCode =3D SCAN_NULL; + Enter.UnicodeChar =3D CHAR_CARRIAGE_RETURN; + Status =3D EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + ASSERT_EFI_ERROR (Status); + + // + // Map F2 and ESC to Boot Manager Menu + // + F2.ScanCode =3D SCAN_F2; + F2.UnicodeChar =3D CHAR_NULL; + Esc.ScanCode =3D SCAN_ESC; + Esc.UnicodeChar =3D CHAR_NULL; + Status =3D EfiBootManagerGetBootManagerMenu (&BootOption); + ASSERT_EFI_ERROR (Status); + Status =3D EfiBootManagerAddKeyOptionVariable ( + NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL + ); + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_ALREADY_STARTED); + Status =3D EfiBootManagerAddKeyOptionVariable ( + NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL + ); + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_ALREADY_STARTED); +} + + +// +// BDS Platform Functions +// +/** + Do the platform init, can be customized by OEM/IBV + Possible things that can be done in PlatformBootManagerBeforeConsole: + > Update console variable: 1. include hot-plug devices; + > 2. Clear ConIn and add SOL for AMT + > Register new Driver#### or Boot#### + > Register new Key####: e.g.: F12 + > Signal ReadyToLock event + > Authentication action: 1. connect Auth devices; + > 2. Identify auto logon user. +**/ +VOID +EFIAPI +PlatformBootManagerBeforeConsole ( + VOID + ) +{ + RETURN_STATUS PcdStatus; + + // + // Signal EndOfDxe PI Event + // + EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); + + // + // Dispatch deferred images after EndOfDxe event. + // + EfiBootManagerDispatchDeferredImages (); + + // + // Locate the PCI root bridges and make the PCI bus driver connect each, + // non-recursively. This will produce a number of child handles with Pci= Io on + // them. + // + FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect); + + // + // Signal the ACPI platform driver that it can download QEMU ACPI tables. + // + EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid); + + // + // Find all display class PCI devices (using the handles from the previo= us + // step), and connect them non-recursively. This should produce a number= of + // child handles with GOPs on them. + // + FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect); + + // + // Now add the device path of all handles with GOP on them to ConOut and + // ErrOut. + // + FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); + + // + // Add the hardcoded short-form USB keyboard device path to ConIn. + // + EfiBootManagerUpdateConsoleVariable (ConIn, + (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL); + + // + // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut. + // + CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid); + EfiBootManagerUpdateConsoleVariable (ConIn, + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + EfiBootManagerUpdateConsoleVariable (ConOut, + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + + // + // Set the front page timeout from the QEMU configuration. + // + PcdStatus =3D PcdSet16S (PcdPlatformBootTimeOut, + GetFrontPageTimeoutFromQemu ()); + ASSERT_RETURN_ERROR (PcdStatus); + + // + // Register platform-specific boot options and keyboard shortcuts. + // + PlatformRegisterOptionsAndKeys (); +} + +/** + Do the platform specific action after the console is ready + Possible things that can be done in PlatformBootManagerAfterConsole: + > Console post action: + > Dynamically switch output mode from 100x31 to 80x25 for certain sena= rino + > Signal console ready platform customized event + > Run diagnostics like memory testing + > Connect certain devices + > Dispatch aditional option roms + > Special boot: e.g.: USB boot, enter UI +**/ +VOID +EFIAPI +PlatformBootManagerAfterConsole ( + VOID + ) +{ + // + // Show the splash screen. + // + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + BootLogoEnableLogo (); + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + + // + // Connect the rest of the devices. + // + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + EfiBootManagerConnectAll (); + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + + // + // Process QEMU's -kernel command line option. Note that the kernel boot= ed + // this way should receive ACPI tables, which is why we connect all devi= ces + // first (see above) -- PCI enumeration blocks ACPI table installation, = if + // there is a PCI host. + // + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + TryRunningQemuKernel (); + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + + // + // Enumerate all possible boot options, then filter and reorder them bas= ed on + // the QEMU configuration. + // + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + EfiBootManagerRefreshAllBootOption (); + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + + // + // Register UEFI Shell + // + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + PlatformRegisterFvBootOption ( + &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE + ); + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + + RemoveStaleFvFileOptions (); + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); + SetBootOrderFromQemu (); + DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole, func: %a, line: %d= \n", __func__, __LINE__)); +} + +/** + This function is called each second during the boot manager waits the + timeout. + + @param TimeoutRemain The remaining timeout. +**/ +VOID +EFIAPI +PlatformBootManagerWaitCallback ( + IN UINT16 TimeoutRemain + ) +{ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White; + UINT16 Timeout; + + Timeout =3D PcdGet16 (PcdPlatformBootTimeOut); + + Black.Raw =3D 0x00000000; + White.Raw =3D 0x00FFFFFF; + + BootLogoUpdateProgress ( + White.Pixel, + Black.Pixel, + L"Start boot option", + White.Pixel, + (Timeout - TimeoutRemain) * 100 / Timeout, + 0 + ); +} + +/** + The function is called when no boot option could be launched, + including platform recovery options and options pointing to applications + built into firmware volumes. + + If this function returns, BDS attempts to enter an infinite loop. +**/ +VOID +EFIAPI +PlatformBootManagerUnableToBoot ( + VOID + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu; + UINTN Index; + + // + // BootManagerMenu doesn't contain the correct information when return s= tatus + // is EFI_NOT_FOUND. + // + Status =3D EfiBootManagerGetBootManagerMenu (&BootManagerMenu); + if (EFI_ERROR (Status)) { + return; + } + // + // Normally BdsDxe does not print anything to the system console, but th= is is + // a last resort -- the end-user will likely not see any DEBUG messages + // logged in this situation. + // + // AsciiPrint () will NULL-check gST->ConOut internally. We check gST->C= onIn + // here to see if it makes sense to request and wait for a keypress. + // + if (gST->ConIn !=3D NULL) { + AsciiPrint ( + "%a: No bootable option or device was found.\n" + "%a: Press any key to enter the Boot Manager Menu.\n", + gEfiCallerBaseName, + gEfiCallerBaseName + ); + Status =3D gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index); + ASSERT_EFI_ERROR (Status); + ASSERT (Index =3D=3D 0); + + // + // Drain any queued keys. + // + while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) { + // + // just throw away Key + // + } + } + + for (;;) { + EfiBootManagerBoot (&BootManagerMenu); + } +} + diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManager= Lib/PlatformBm.h b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootM= anagerLib/PlatformBm.h new file mode 100644 index 0000000000..427ecf1154 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pla= tformBm.h @@ -0,0 +1,112 @@ +/** @file + Head file for BDS Platform specific code + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef PLATFORM_BM_H_ +#define PLATFORM_BM_H_ + +#include + +#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >>= 8) } + +#define SERIAL_DXE_FILE_GUID { \ + 0xD3987D4B, 0x971A, 0x435F, \ + { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \ + } + +#define ALIGN_UP(addr, align) \ + ((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1)) + +#pragma pack (1) +typedef struct { + VENDOR_DEVICE_PATH SerialDxe; + UART_DEVICE_PATH Uart; + VENDOR_DEFINED_DEVICE_PATH TermType; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_SERIAL_CONSOLE; +#pragma pack () + +#pragma pack (1) +typedef struct { + USB_CLASS_DEVICE_PATH Keyboard; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_USB_KEYBOARD; +#pragma pack () + +/** + Check if the handle satisfies a particular condition. + + @param[in] Handle The handle to check. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. + + @retval TRUE The condition is satisfied. + @retval FALSE Otherwise. This includes the case when the condition coul= d not + be fully evaluated due to an error. +**/ +typedef +BOOLEAN +(EFIAPI *FILTER_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + +/** + Process a handle. + + @param[in] Handle The handle to process. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. +**/ +typedef +VOID +(EFIAPI *CALLBACK_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + +/** + * execute from kernel entry point. + * + * @param[in] Argc The count of args. + * @param[in] Argv The pointer to args array. + * @param[in] Bpi The pointer to bootparaminterface struct. + * @param[in] Vec The fourth args for kernel. + ***/ +typedef +VOID +(EFIAPI *EFI_KERNEL_ENTRY_POINT) ( + IN UINTN Argc, + IN VOID *Argv, + IN VOID *Bpi, + IN VOID *Vec + ); + +/** + Download the kernel, the initial ramdisk, and the kernel command line fr= om + QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two + image files, and load and start the kernel from it. + + The kernel will be instructed via its command line to load the initrd fr= om + the same Simple FileSystem. + + @retval EFI_NOT_FOUND Kernel image was not found. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + @retval EFI_PROTOCOL_ERROR Unterminated kernel command line. + + @return Error codes from any of the underlying + functions. On success, the function doesn't + return. +**/ +EFI_STATUS +EFIAPI +TryRunningQemuKernel ( + VOID + ); + +#endif // _PLATFORM_BM_H_ diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManager= Lib/PlatformBootManagerLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library= /PlatformBootManagerLib/PlatformBootManagerLib.inf new file mode 100644 index 0000000000..0f322b30f6 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pla= tformBootManagerLib.inf @@ -0,0 +1,78 @@ +## @file +# Implementation for PlatformBootManagerLib library class interfaces. +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PlatformBootManagerLib + FILE_GUID =3D 469184E8-FADA-41E4-8823-012CA19B40D4 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D PlatformBootManagerLib|DXE_DRIVER + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D LOONGARCH64 +# + +[Sources] + PlatformBm.c + QemuKernel.c + +[Packages] + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + BootLogoLib + DebugLib + DevicePathLib + MemoryAllocationLib + PcdLib + PrintLib + QemuBootOrderLib + QemuLoadImageLib + QemuFwCfgLib + UefiBootManagerLib + UefiBootServicesTableLib + UefiLib + UefiRuntimeServicesTableLib + +[FixedPcd] + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut + +[Guids] + gEfiFileInfoGuid + gEfiFileSystemInfoGuid + gEfiFileSystemVolumeLabelInfoIdGuid + gEfiEndOfDxeEventGroupGuid + gRootBridgesConnectedEventGroupGuid + gUefiShellFileGuid + gEfiLoongsonBootparamsTableGuid ## SOMETIM= ES_PRODUCES ## SystemTable + gEfiTtyTermGuid + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiFirmwareVolume2ProtocolGuid + gEfiGraphicsOutputProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiPciRootBridgeIoProtocolGuid + gEfiSimpleFileSystemProtocolGuid diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManager= Lib/QemuKernel.c b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootM= anagerLib/QemuKernel.c new file mode 100644 index 0000000000..ceb131d566 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Qem= uKernel.c @@ -0,0 +1,81 @@ +/** @file + Try to run Linux kernel. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - mem - Memory + - Bpi - Boot Parameter Interface + - FwCfg - FirmWare Configure +**/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Download the kernel, the initial ramdisk, and the kernel command line fr= om + QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two + image files, and load and start the kernel from it. + + The kernel will be instructed via its command line to load the initrd fr= om + the same Simple FileSystem. + + @retval EFI_NOT_FOUND Kernel image was not found. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + @retval EFI_PROTOCOL_ERROR Unterminated kernel command line. + + @return Error codes from any of the underlying + functions. On success, the function doesn't + return. +**/ +EFI_STATUS +TryRunningQemuKernel ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE KernelImageHandle; + + Status =3D QemuLoadKernelImage (&KernelImageHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Signal the EFI_EVENT_GROUP_READY_TO_BOOT event. + // + EfiSignalEventReadyToBoot (); + + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT) + ); + + // + // Start the image. + // + Status =3D QemuStartKernelImage (&KernelImageHandle); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: QemuStartKernelImage(): %r\n", + __FUNCTION__, + Status + )); + } + + QemuUnloadKernelImage (KernelImageHandle); + + return Status; +} --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93895): https://edk2.groups.io/g/devel/message/93895 Mute This Topic: https://groups.io/mt/93715814/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93903+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93903+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299421; cv=none; d=zohomail.com; s=zohoarc; b=iDzTJSUqIKEDGszSxsd3AcMN265560rqafiAEIT/u+1HwyNDXLZnFKcf9BqAnA+1VsQ8CZrr9W4vE+8AmA39eFDyx6dT0S6ssSaT6Vx//AjS6HUgpV23Pd4Zenp1StMMplOqQQj+oeDgTAfZkJefcd6oY14wbYaIA6iUZGx3Phc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299421; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=yBN6gW8FbqioSWqif+11r1lsYpNvjrUiJVWhi4D2p64=; b=H3MTXYwqqQh5k86TWpgK8BAIS44EtJUIxLwIGW6Vj82521pwITook3hQSLbrxNg0PAQDKKxnR5HeeGOWBxwZvG7ZXyE1aaEazwNr63Gn3vU2YaRF3Q4Fa6yTtbwmgmQs8JIWeTAYmOqMuhrgsro9V3tdyrzRLMtG00YqwA7t3cw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93903+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299421673237.7555820304848; Thu, 15 Sep 2022 20:37:01 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id cSYhYY1788612xMamPxA9JCV; Thu, 15 Sep 2022 20:37:01 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web08.2163.1663299413461243947 for ; Thu, 15 Sep 2022 20:37:00 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S15; Fri, 16 Sep 2022 11:36:43 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 13/16] Platform/Loongson: Add Reset System Lib. Date: Fri, 16 Sep 2022 11:36:30 +0800 Message-Id: <3f8acac36ae0209d4a4e738f18e179c1949affc4.1663298005.git.lixianglai@loongson.cn> In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S15 X-Coremail-Antispam: 1UD129KBjvAXoWftr1fCw13ZF18ZrWxJFy7Wrg_yoW8uw47to W2gan7t3y8Jrs5u397Wrn3GF4IqFsYq398ZF1rJFWUJrWDZr109FWvqay8JF93tFn8XF45 GayfJ3yrJrWagF4kn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: bvaQ5Q6lExPKvfdVvRctVVOgx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299421; bh=LG/dSvzqif/Hiye6kltp6xTm6CIlngkV26P4/8TBqwo=; h=Cc:Date:From:Reply-To:Subject:To; b=iKWdAFpN6I29sqwiRtWMjADTj51lLaRp1M7qHIhQdr+lLbGniqaIyyzAxnP7E91l5gu 9PaSSUb+QTIOCL8WxHD3fBSN46WgoNGsusWueHBGUkrD5Q67tg74HoEd+9qtzDqv7mR2R Yn/T3BXP38ApXLDm0qhJk7opERSM5oXiN40= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299422354100005 Content-Type: text/plain; charset="utf-8" This library provides interfaces related to restart and shutdown. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../BaseResetSystemAcpiGed.c | 155 ++++++++++ .../BaseResetSystemAcpiGedLib.inf | 42 +++ .../DxeResetSystemAcpiGed.c | 270 ++++++++++++++++++ .../DxeResetSystemAcpiGedLib.inf | 47 +++ .../ResetSystemAcpiLib/ResetSystemAcpiGed.c | 128 +++++++++ .../ResetSystemAcpiLib/ResetSystemAcpiGed.h | 20 ++ 6 files changed, 662 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemA= cpiLib/BaseResetSystemAcpiGed.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemA= cpiLib/BaseResetSystemAcpiGedLib.inf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemA= cpiLib/DxeResetSystemAcpiGed.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemA= cpiLib/DxeResetSystemAcpiGedLib.inf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemA= cpiLib/ResetSystemAcpiGed.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemA= cpiLib/ResetSystemAcpiGed.h diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/= BaseResetSystemAcpiGed.c b/Platform/Loongson/LoongArchQemuPkg/Library/Reset= SystemAcpiLib/BaseResetSystemAcpiGed.c new file mode 100644 index 0000000000..a50672410b --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseRes= etSystemAcpiGed.c @@ -0,0 +1,155 @@ +/** @file + Base ResetSystem library implementation. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include "ResetSystemAcpiGed.h" +#include + +/** + Get configuration item data by the firmware configuration file name. + + @param[in] Name - Name of file to look up. + + @return VOID* The Pointer of Value of Firmware Configuration it= em read. + +**/ +VOID * +GetFwCfgData( +CONST CHAR8 *Name +) +{ + FIRMWARE_CONFIG_ITEM FwCfgItem; + EFI_STATUS Status; + UINTN FwCfgSize; + VOID *Data; + + Status =3D QemuFwCfgFindFile (Name, &FwCfgItem, &FwCfgSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a %d read %s error Status %d \n", __func__, __= LINE__, Name, Status)); + return NULL; + } + + Data =3D AllocatePool (FwCfgSize); + if (Data =3D=3D NULL) { + return NULL; + } + + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (FwCfgSize, Data); + + return Data; +} + +/** + Find the power manager related info from ACPI table + + + @retval RETURN_SUCCESS Successfully find out all the required inform= ation. + @retval RETURN_NOT_FOUND Failed to find the required info. + +**/ +STATIC EFI_STATUS +GetPowerManagerByParseAcpiInfo (VOID) +{ + EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt =3D NULL; + EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp =3D NULL; + EFI_ACPI_DESCRIPTION_HEADER *Xsdt =3D NULL; + EFI_ACPI_DESCRIPTION_HEADER *Rsdt =3D NULL; + VOID *AcpiTables =3D NULL; + UINT32 *Entry32 =3D NULL; + UINTN Entry32Num; + UINT32 *Signature =3D NULL; + UINTN Idx; + + Rsdp =3D GetFwCfgData ("etc/acpi/rsdp"); + if (Rsdp =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a %d read etc/acpi/rsdp error \n", __func__, __= LINE__)); + return RETURN_NOT_FOUND; + } + + AcpiTables =3D GetFwCfgData ("etc/acpi/tables"); + if (AcpiTables =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a %d read etc/acpi/tables error \n", __func__, = __LINE__)); + FreePool (Rsdp); + return RETURN_NOT_FOUND; + } + + Rsdt =3D (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)AcpiTables + Rsdp->Rsdt= Address); + Entry32 =3D (UINT32 *)(Rsdt + 1); + Entry32Num =3D (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> = 2; + for (Idx =3D 0; Idx < Entry32Num; Idx++) { + Signature =3D (UINT32 *)((UINTN)Entry32[Idx] + (UINTN)AcpiTables); + if (*Signature =3D=3D EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNAT= URE) { + Fadt =3D (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; + DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n")); + goto Done; + } + } + + + Xsdt =3D (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)AcpiTables + Rsdp->Xsdt= Address); + Entry32 =3D (UINT32 *)(Xsdt + 1); + Entry32Num =3D (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> = 2; + for (Idx =3D 0; Idx < Entry32Num; Idx++) { + Signature =3D (UINT32 *)((UINTN)Entry32[Idx] + (UINTN)AcpiTables); + if (*Signature =3D=3D EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNAT= URE) { + Fadt =3D (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; + DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n")); + goto Done; + } + } + + + FreePool (Rsdp); + FreePool (AcpiTables); + DEBUG ((DEBUG_ERROR, " Fadt Not Found\n")); + return RETURN_NOT_FOUND; + +Done: + + mPowerManager.ResetRegAddr =3D Fadt->ResetReg.Address; + mPowerManager.ResetValue =3D Fadt->ResetValue; + mPowerManager.SleepControlRegAddr =3D Fadt->SleepControlReg.Address; + mPowerManager.SleepStatusRegAddr =3D Fadt->SleepStatusReg.Address; + + FreePool (Rsdp); + FreePool (AcpiTables); + + return RETURN_SUCCESS; +} + +/** + The constructor function to initialize mPowerManager. + + @retval EFI_SUCCESS initialize mPowerManager success. + @retval RETURN_NOT_FOUND Failed to initialize mPowerManager. + +**/ +EFI_STATUS +ResetSystemLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status =3D GetPowerManagerByParseAcpiInfo (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a:%d\n", __FUNCTION__, __LINE__)); + } + + ASSERT (mPowerManager.SleepControlRegAddr); + ASSERT (mPowerManager.SleepStatusRegAddr); + ASSERT (mPowerManager.ResetRegAddr); + + return Status; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/= BaseResetSystemAcpiGedLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/= ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf new file mode 100644 index 0000000000..2336732e35 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/BaseRes= etSystemAcpiGedLib.inf @@ -0,0 +1,42 @@ +## @file +# Base library instance for ResetSystem library class for loongarhch +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 1.29 + BASE_NAME =3D ResetSystemLib + FILE_GUID =3D 3d6faf60-804a-4ca9-a36a-1a92416919d0 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D ResetSystemLib|SEC PEI_CORE PEIM DXE_= CORE + CONSTRUCTOR =3D ResetSystemLibConstructor + +# +# The following information is for reference only and not required by the = build +# tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources] + BaseResetSystemAcpiGed.c + ResetSystemAcpiGed.c + + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + QemuFwCfgLib + MemoryAllocationLib + IoLib + diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/= DxeResetSystemAcpiGed.c b/Platform/Loongson/LoongArchQemuPkg/Library/ResetS= ystemAcpiLib/DxeResetSystemAcpiGed.c new file mode 100644 index 0000000000..7d2aea53f4 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeRese= tSystemAcpiGed.c @@ -0,0 +1,270 @@ +/** @file + Dxe ResetSystem library implementation. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include // EfiConvertPointer() +#include +#include +#include "ResetSystemAcpiGed.h" +#include + +/** + Modifies the attributes to Runtime type for a page size memory region. + + @param BaseAddress Specified start address + + @retval EFI_SUCCESS The attributes were set for the memory reg= ion. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The processor does not support one or more= bytes of the memory + resource range specified by BaseAddress an= d Length. + @retval EFI_UNSUPPORTED The bit mask of attributes is not support = for the memory resource + range specified by BaseAddress and Length. + @retval EFI_ACCESS_DEFINED The attributes for the memory resource ran= ge specified by + BaseAddress and Length cannot be modified. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to m= odify the attributes of + the memory resource range. + @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU a= rchitectural protocol is + not available yet. + +**/ +EFI_STATUS +SetMemoryAttributesRunTime ( + UINTN Address + ) +{ + EFI_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + + Address &=3D ~EFI_PAGE_MASK; + + Status =3D gDS->GetMemorySpaceDescriptor (Address, &Descriptor); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: GetMemorySpaceDescriptor failed\n", __FUNCTIO= N__)); + return Status; + } + + if (Descriptor.GcdMemoryType =3D=3D EfiGcdMemoryTypeNonExistent) { + Status =3D gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + Address, + EFI_PAGE_SIZE, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: AddMemorySpace failed\n", __FUNCTION__)); + return Status; + } + + Status =3D gDS->SetMemorySpaceAttributes ( + Address, + EFI_PAGE_SIZE, + EFI_MEMORY_RUNTIME + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __FUN= CTION__, __LINE__)); + return Status; + } + } else if (!(Descriptor.Attributes & EFI_MEMORY_RUNTIME)) { + Status =3D gDS->SetMemorySpaceAttributes ( + Address, + EFI_PAGE_SIZE, + Descriptor.Attributes | EFI_MEMORY_RUNTIME + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __FUN= CTION__, __LINE__)); + return Status; + } + } + + return EFI_SUCCESS; +} + +/** + Find the power manager related info from ACPI table + + + @retval RETURN_SUCCESS Successfully find out all the required inform= ation. + @retval RETURN_NOT_FOUND Failed to find the required info. + +**/ +STATIC EFI_STATUS +GetPowerManagerByParseAcpiInfo ( + VOID +) +{ + EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt =3D NULL; + EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp =3D NULL; + EFI_ACPI_DESCRIPTION_HEADER *Xsdt =3D NULL; + EFI_ACPI_DESCRIPTION_HEADER *Rsdt =3D NULL; + UINT32 *Entry32 =3D NULL; + UINTN Entry32Num; + UINT32 *Signature =3D NULL; + UINTN Idx; + EFI_STATUS Status; + + Status =3D EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **)= &Rsdp); + if (EFI_ERROR (Status)) { + Status =3D EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID= **)&Rsdp); + } + + if (EFI_ERROR (Status) || (Rsdp =3D=3D NULL)) { + DEBUG ((DEBUG_ERROR, "EFI_ERROR or Rsdp =3D=3D NULL\n")); + return RETURN_NOT_FOUND; + } + + Rsdt =3D (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress; + Entry32 =3D (UINT32 *)(UINTN)(Rsdt + 1); + Entry32Num =3D (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> = 2; + for (Idx =3D 0; Idx < Entry32Num; Idx++) { + Signature =3D (UINT32 *)(UINTN)Entry32[Idx]; + if (*Signature =3D=3D EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNAT= URE) { + Fadt =3D (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; + DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n")); + goto Done; + } + } + + + Xsdt =3D (EFI_ACPI_DESCRIPTION_HEADER *)Rsdp->XsdtAddress; + Entry32 =3D (UINT32 *)(Xsdt + 1); + Entry32Num =3D (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> = 2; + for (Idx =3D 0; Idx < Entry32Num; Idx++) { + Signature =3D (UINT32 *)(UINTN)Entry32[Idx]; + if (*Signature =3D=3D EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNAT= URE) { + Fadt =3D (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; + DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n")); + goto Done; + } + } + + + DEBUG ((DEBUG_ERROR, " Fadt Not Found\n")); + return RETURN_NOT_FOUND; + +Done: + + mPowerManager.ResetRegAddr =3D Fadt->ResetReg.Address; + mPowerManager.ResetValue =3D Fadt->ResetValue; + mPowerManager.SleepControlRegAddr =3D Fadt->SleepControlReg.Address; + mPowerManager.SleepStatusRegAddr =3D Fadt->SleepStatusReg.Address; + + return RETURN_SUCCESS; + +} + +/** + This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS= _CHANGE + event. It converts a pointer to a new virtual address. + + @param[in] Event Event whose notification function is being invok= ed. + @param[in] Context Pointer to the notification function's context +**/ +VOID +EFIAPI +ResetSystemLibAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EfiConvertPointer (0, (VOID **)&mPowerManager.SleepControlRegAddr); + EfiConvertPointer (0, (VOID **)&mPowerManager.SleepStatusRegAddr); + EfiConvertPointer (0, (VOID **)&mPowerManager.ResetRegAddr); +} + +/** + Notification function of ACPI Table change. + + This is a notification function registered on ACPI Table change event. + It saves the Century address stored in ACPI FADT table. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context. + +**/ +STATIC VOID +AcpiNotificationEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + Status =3D GetPowerManagerByParseAcpiInfo (); + if (EFI_ERROR (Status)) { + return ; + } + + DEBUG ((DEBUG_INFO, "%a: sleepControl %llx\n", __FUNCTION__, mPowerManag= er.SleepControlRegAddr)); + ASSERT (mPowerManager.SleepControlRegAddr); + Status =3D SetMemoryAttributesRunTime (mPowerManager.SleepControlRegAdd= r); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a:%d\n", __FUNCTION__, __LINE__)); + return ; + } + + DEBUG ((DEBUG_INFO, "%a: sleepStatus %llx\n", __FUNCTION__, mPowerManage= r.SleepStatusRegAddr)); + ASSERT (mPowerManager.SleepStatusRegAddr); + Status =3D SetMemoryAttributesRunTime (mPowerManager.SleepStatusRegAddr= ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a:%d\n", __FUNCTION__, __LINE__)); + return ; + } + + DEBUG ((DEBUG_INFO, "%a: ResetReg %llx\n", __FUNCTION__, mPowerManager.R= esetRegAddr)); + ASSERT (mPowerManager.ResetRegAddr); + Status =3D SetMemoryAttributesRunTime (mPowerManager.ResetRegAddr); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a:%d\n", __FUNCTION__, __LINE__)); + } + + return ; +} + +/** + The constructor function to Register ACPI Table change event and Address= Change Event. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +ResetSystemLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + EFI_EVENT ResetSystemVirtualNotifyEvent; + + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + AcpiNotificationEvent, + NULL, + &gEfiAcpiTableGuid, + &Event + ); + + // + // Register SetVirtualAddressMap () notify function + // + Status =3D gBS->CreateEvent ( + EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + TPL_NOTIFY, + ResetSystemLibAddressChangeEvent, + NULL, + &ResetSystemVirtualNotifyEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/= DxeResetSystemAcpiGedLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/R= esetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf new file mode 100644 index 0000000000..6ba78574b5 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/DxeRese= tSystemAcpiGedLib.inf @@ -0,0 +1,47 @@ +## @file +# DXE library instance for ResetSystem library class for loongarch. +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 1.29 + BASE_NAME =3D ResetSystemLib + FILE_GUID =3D 3d6faf60-804a-4ca9-a36a-1a92416919d0 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D ResetSystemLib|DXE_DRIVER DXE_RUNTIME= _DRIVER SMM_CORE DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION + CONSTRUCTOR =3D ResetSystemLibConstructor + +# +# The following information is for reference only and not required by the = build +# tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources] + DxeResetSystemAcpiGed.c + ResetSystemAcpiGed.c + + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + DxeServicesTableLib + IoLib + UefiLib + +[Guids] + gEfiAcpi10TableGuid ## PRODUCES ## S= ystemTable + gEfiAcpiTableGuid ## PRODUCES ## S= ystemTable + + diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/= ResetSystemAcpiGed.c b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSyst= emAcpiLib/ResetSystemAcpiGed.c new file mode 100644 index 0000000000..7f88269f13 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSy= stemAcpiGed.c @@ -0,0 +1,128 @@ +/** @file + ResetSystem library implementation. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include // CpuDeadLoop() +#include +#include // ResetCold() +#include +#include "ResetSystemAcpiGed.h" + +POWER_MANAGER mPowerManager; + +/** + Calling this function causes a system-wide reset. This sets + all circuitry within the system to its initial state. This type of reset + is asynchronous to system operation and operates without regard to + cycle boundaries. + + System reset should not return, if it returns, it means the system does + not support cold reset. +**/ +STATIC VOID +AcpiGedReset ( + VOID + ) +{ + MmioWrite8 ( + (UINTN)mPowerManager.ResetRegAddr, + mPowerManager.ResetValue + ); + + CpuDeadLoop (); +} + +/** + This function causes the system to enter a power state equivalent + to the ACPI S5 states. + + * */ +STATIC VOID +AcpiGedShutdown ( + VOID + ) +{ + MmioWrite8 ( + (UINTN)mPowerManager.SleepControlRegAddr, + (1 << 5) /* enable bit */ | + (5 << 2) /* typ =3D=3D S5 */ + ); + + CpuDeadLoop (); +} + +/** + This function causes a system-wide reset (cold reset), in which + all circuitry within the system returns to its initial state. This type = of + reset is asynchronous to system operation and operates without regard to + cycle boundaries. + + If this function returns, it means that the system does not support cold + reset. +**/ +VOID EFIAPI +ResetCold ( + VOID + ) +{ + AcpiGedReset (); +} + +/** + This function causes a system-wide initialization (warm reset), in which= all + processors are set to their initial state. Pending cycles are not corrup= ted. + + If this function returns, it means that the system does not support warm + reset. +**/ +VOID EFIAPI +ResetWarm ( + VOID + ) +{ + AcpiGedReset (); +} + +/** + This function causes a systemwide reset. The exact type of the reset is + defined by the EFI_GUID that follows the Null-terminated Unicode string = passed + into ResetData. If the platform does not recognize the EFI_GUID in Reset= Data + the platform must pick a supported reset type to perform.The platform may + optionally log the parameters from any non-normal reset that occurs. + + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData The data buffer starts with a Null-terminated str= ing, + followed by the EFI_GUID. +**/ +VOID +EFIAPI +ResetPlatformSpecific ( + IN UINTN DataSize, + IN VOID *ResetData + ) +{ + AcpiGedReset (); +} + +/** + This function causes the system to enter a power state equivalent + to the ACPI G2/S5 or G3 states. + + If this function returns, it means that the system does not support shut= down + reset. +**/ +VOID EFIAPI +ResetShutdown ( + VOID + ) +{ + AcpiGedShutdown (); +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/= ResetSystemAcpiGed.h b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSyst= emAcpiLib/ResetSystemAcpiGed.h new file mode 100644 index 0000000000..08288da1e8 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/ResetSystemAcpiLib/ResetSy= stemAcpiGed.h @@ -0,0 +1,20 @@ +/** @file + ResetSystem lib head file. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +typedef struct { + UINT64 SleepControlRegAddr; + UINT64 SleepStatusRegAddr; + UINT64 ResetRegAddr; + UINT8 ResetValue; +} POWER_MANAGER; + +extern POWER_MANAGER mPowerManager; + --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93903): https://edk2.groups.io/g/devel/message/93903 Mute This Topic: https://groups.io/mt/93715822/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93898+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93898+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299410; cv=none; d=zohomail.com; s=zohoarc; b=Pa1LiGG6ptlB1A8c6O0hSNElfKqnDuofV/yLRDf7FOqIlkkype4h8vdZQzOVUiTMPHe6ItJpVmXAmwPcCr6u+it2ziqy/mG8VenYuq/pnx8SRIzWm9UZ/79IIlhYWYxbnpU3FsYdOGOU9TI7Z55XLBGOAODHC3KA5Zg2/RD9Qq8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299410; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=QYsa7cZFMWjOEY5oKJpOAlCLns63mjaa1MOmKmxHL2U=; b=J+tQCG+x2xRxE/fKfy828+5fG3D4TwcIZRToQdF4DgdOSXO/hTuLS6JVPpKg4Y/CkG++DdXi71dth4on5gx/zMIW+yxf8gvIgOVgelpN5E7gSEutGfMBruQ48heE8pXyZVwrp8Qepek63whiH5MeK52V9AlrFs6SQuqoztGc7mM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93898+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299410691908.3657366686241; Thu, 15 Sep 2022 20:36:50 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id YtcpYY1788612x9aVFsn7j03; Thu, 15 Sep 2022 20:36:50 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web10.2139.1663299406612063453 for ; Thu, 15 Sep 2022 20:36:49 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S16; Fri, 16 Sep 2022 11:36:44 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 14/16] Platform/Loongson: Support Dxe Date: Fri, 16 Sep 2022 11:36:31 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S16 X-Coremail-Antispam: 1UD129KBjvAXoWDAryruFW7uw48GF13GF45KFg_yoWruw4fto Z7JF1jyr45Kr1kJ3yUKFs8try7ZwsIvrs0qr18Zw1kAF4Utr12yrWDtwnrWr1DAFn8Ar1D G3y5J3y8JrW7twn7n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: GwM2B5OgXgWCqD5C7la5foWQx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299410; bh=MaDrALcwH4Pskdgunmpwt2KIMUpPbTDlRmnJdyh5rmU=; h=Cc:Date:From:Reply-To:Subject:To; b=HMfxu+I3dqz3lzrP/x82VDJuAfgQuTCtfDQwAv52g6XVCsb1F5CGWVy5vosyjb+z0MX mBLjSSee+jvqC6ks+4L2GyId4aEAyKnreHNRVchivJCcHs6TVUXORKwubgQnCzCZXdhtI JGjMIkxaX3w0rYwLds8RqcmD/wCFiOSNR+k= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299412408100043 Content-Type: text/plain; charset="utf-8" Support Dxe for LoogArch. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../Loongson/LoongArchQemuPkg/Loongson.dec | 14 +- .../Loongson/LoongArchQemuPkg/Loongson.dsc | 420 +++++++++++++++++- .../Loongson/LoongArchQemuPkg/Loongson.fdf | 243 ++++++++++ .../LoongArchQemuPkg/Loongson.fdf.inc | 42 ++ .../LoongArchQemuPkg/VarStore.fdf.inc | 64 +++ 5 files changed, 778 insertions(+), 5 deletions(-) create mode 100644 Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.dec index aca53583f1..508a770a22 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec @@ -18,7 +18,8 @@ # Comments are used for Keywords and Module Types. # # Supported Module Types: -# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_D= RIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_D= RIVER +# DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION # ##########################################################################= ###### [Includes.common] @@ -26,12 +27,20 @@ =20 [Guids] gLoongArchQemuPkgTokenSpaceGuid =3D { 0x0e0383ce, 0x0151, 0x4d01, { 0x8= 0, 0x0e, 0x3f, 0xef, 0x8b, 0x27, 0x6d, 0x52 } } + gEfiLoongsonBootparamsTableGuid =3D { 0x4660f721, 0x2ec5, 0x416a, { 0x8= 9, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } } + +[Protocols] =20 [PcdsFixedAtBuild, PcdsDynamic] gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase|0x0|UINT64|0x00000003 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize|0x0|UINT32|0x00000004 + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvOffset|0x0|UINT64|0x00000007 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvBase|0x0|UINT64|0x00000008 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvSize|0x0|UINT32|0x00000009 + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecModuleBase|0x0|UINT64|0x00000= 00a + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecModuleSize|0x0|UINT32|0x00000= 00b + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashEventLogBase|0x0|UINT64|0x000000= 0c + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashEventLogSize|0x0|UINT32|0x000000= 0d gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0|UINT3= 2|0x00000016 gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|0|UI= NT32|0x00000017 gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase|0x0|UINT64|0x00000018 @@ -47,6 +56,8 @@ [PcdsFixedAtBuild.LOONGARCH64] gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32|UINT8|0x00000010 gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0|UINT8|0x00000011 + gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceSpaceStartAddress|0x10000000|U= INT32|0x00000012 + gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceSpaceLength|0x80000000|UINT32|= 0x00000013 =20 [PcdsDynamic] gLoongArchQemuPkgTokenSpaceGuid.PcdRamSize|0x40000000|UINT64|0x00000041 @@ -58,3 +69,4 @@ gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPmd|0x0|UINT64|0x00000047 gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPte|0x0|UINT64|0x00000048 =20 +[PcdsFeatureFlag] diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.dsc index 09b324c3f7..578b80b7b0 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc @@ -24,6 +24,25 @@ FLASH_DEFINITION =3D Platform/Loongson/LoongArchQemuPkg/Lo= ongson.fdf TTY_TERMINAL =3D FALSE =20 + # + # Defines for default states. These can be changed on the command line. + # -D FLAG=3DVALUE + DEFINE TTY_TERMINAL =3D FALSE + DEFINE SECURE_BOOT_ENABLE =3D FALSE + DEFINE TPM2_ENABLE =3D FALSE + DEFINE TPM2_CONFIG_ENABLE =3D FALSE + + # + # Network definition + # + DEFINE NETWORK_IP6_ENABLE =3D FALSE + DEFINE NETWORK_HTTP_BOOT_ENABLE =3D FALSE + DEFINE NETWORK_SNP_ENABLE =3D FALSE + DEFINE NETWORK_TLS_ENABLE =3D FALSE + DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS =3D TRUE + DEFINE NETWORK_ISCSI_ENABLE =3D FALSE + +!include NetworkPkg/NetworkDefines.dsc.inc ##########################################################################= ## # # Defines for default states. These can be changed on the command line. @@ -37,16 +56,25 @@ # GCC:*_*_*_CC_FLAGS =3D -D DISABLE_NEW_DEPRECATED_INTERFACES =20 +!include NetworkPkg/NetworkBuildOptions.dsc.inc =20 [BuildOptions.LOONGARCH64.EDKII.SEC] *_*_*_CC_FLAGS =3D =20 -#[BuildOptions.common.EDKII.DXE_CORE,BuildOptions.common.EDKII.DXE_DRIVER,= BuildOptions.common.EDKII.UEFI_DRIVER,BuildOptions.common.EDKII.UEFI_APPLIC= ATION] -# GCC:*_*_*_DLINK_FLAGS =3D -z common-page-size=3D0x1000 +[BuildOptions.common.EDKII.DXE_CORE,BuildOptions.common.EDKII.DXE_DRIVER,B= uildOptions.common.EDKII.UEFI_DRIVER,BuildOptions.common.EDKII.UEFI_APPLICA= TION] + GCC:*_*_*_DLINK_FLAGS =3D -z common-page-size=3D0x1000 =20 [BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER] GCC:*_*_LOONGARCH64_DLINK_FLAGS =3D -z common-page-size=3D0x10000 =20 +##########################################################################= ###### +# +# SKU Identification section - list of all SKU IDs supported by this Platf= orm. +# +##########################################################################= ###### +[SkuIds] + 0|DEFAULT + ##########################################################################= ###### # # Library Class section - list of all Library Classes needed by this Platf= orm. @@ -61,19 +89,88 @@ PrintLib | MdePkg/Library/BasePrintLib/BasePrint= Lib.inf BaseMemoryLib | MdePkg/Library/BaseMemoryLib/BaseMemo= ryLib.inf =20 + # Networking Requirements +!include NetworkPkg/NetworkLibs.dsc.inc +!if $(NETWORK_TLS_ENABLE) =3D=3D TRUE + TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf +!endif =20 BaseLib | MdePkg/Library/BaseLib/BaseLib.inf + SafeIntLib | MdePkg/Library/BaseSafeIntLib/BaseSaf= eIntLib.inf + TimeBaseLib | EmbeddedPkg/Library/TimeBaseLib/TimeB= aseLib.inf + BmpSupportLib | MdeModulePkg/Library/BaseBmpSupportLi= b/BaseBmpSupportLib.inf + SynchronizationLib | MdePkg/Library/BaseSynchronizationLib= /BaseSynchronizationLib.inf + CpuLib | MdePkg/Library/BaseCpuLib/BaseCpuLib.= inf PerformanceLib | MdePkg/Library/BasePerformanceLibNull= /BasePerformanceLibNull.inf PeCoffLib | MdePkg/Library/BasePeCoffLib/BasePeCo= ffLib.inf CacheMaintenanceLib | MdePkg/Library/BaseCacheMaintenanceLi= b/BaseCacheMaintenanceLib.inf UefiDecompressLib | MdePkg/Library/BaseUefiDecompressLib/= BaseUefiDecompressLib.inf + UefiHiiServicesLib | MdeModulePkg/Library/UefiHiiServicesL= ib/UefiHiiServicesLib.inf + HiiLib | MdeModulePkg/Library/UefiHiiLib/UefiH= iiLib.inf + CapsuleLib | MdeModulePkg/Library/DxeCapsuleLibNul= l/DxeCapsuleLibNull.inf + DxeServicesLib | MdePkg/Library/DxeServicesLib/DxeServ= icesLib.inf + DxeServicesTableLib | MdePkg/Library/DxeServicesTableLib/Dx= eServicesTableLib.inf PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPoin= tLib/BasePeCoffGetEntryPointLib.inf + PciLib | MdePkg/Library/BasePciLibPciExpress/B= asePciLibPciExpress.inf + PciExpressLib | OvmfPkg/Library/BaseCachingPciExpress= Lib/BaseCachingPciExpressLib.inf + PciCapLib | OvmfPkg/Library/BasePciCapLib/BasePci= CapLib.inf + PciCapPciSegmentLib | OvmfPkg/Library/BasePciCapPciSegmentL= ib/BasePciCapPciSegmentLib.inf + PciCapPciIoLib | OvmfPkg/Library/UefiPciCapPciIoLib/Ue= fiPciCapPciIoLib.inf IoLib | MdePkg/Library/BaseIoLibIntrinsic/Bas= eIoLibIntrinsic.inf SerialPortLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/SerialPortLib/SerialPortLib.inf + EfiResetSystemLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf + ResetSystemLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/ResetSystemAcpiLib/BaseResetSystemAcpiGedLib.inf + + UefiLib | MdePkg/Library/UefiLib/UefiLib.inf + UefiBootServicesTableLib | MdePkg/Library/UefiBootServicesTableL= ib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib | MdePkg/Library/UefiRuntimeServicesTab= leLib/UefiRuntimeServicesTableLib.inf + UefiDriverEntryPoint | MdePkg/Library/UefiDriverEntryPoint/U= efiDriverEntryPoint.inf + UefiApplicationEntryPoint | MdePkg/Library/UefiApplicationEntryPo= int/UefiApplicationEntryPoint.inf + DevicePathLib | MdePkg/Library/UefiDevicePathLibDevic= ePathProtocol/UefiDevicePathLibDevicePathProtocol.inf + FileHandleLib | MdePkg/Library/UefiFileHandleLib/Uefi= FileHandleLib.inf + SecurityManagementLib | MdeModulePkg/Library/DxeSecurityManag= ementLib/DxeSecurityManagementLib.inf + UefiUsbLib | MdePkg/Library/UefiUsbLib/UefiUsbLib.= inf + SerializeVariablesLib | OvmfPkg/Library/SerializeVariablesLib= /SerializeVariablesLib.inf + CustomizedDisplayLib | MdeModulePkg/Library/CustomizedDispla= yLib/CustomizedDisplayLib.inf DebugPrintErrorLevelLib | MdePkg/Library/BaseDebugPrintErrorLev= elLib/BaseDebugPrintErrorLevelLib.inf + TpmMeasurementLib | MdeModulePkg/Library/TpmMeasurementLi= bNull/TpmMeasurementLibNull.inf + AuthVariableLib | MdeModulePkg/Library/AuthVariableLibN= ull/AuthVariableLibNull.inf + VarCheckLib | MdeModulePkg/Library/VarCheckLib/VarC= heckLib.inf + VariablePolicyLib | MdeModulePkg/Library/VariablePolicyLi= b/VariablePolicyLib.inf + VariablePolicyHelperLib | MdeModulePkg/Library/VariablePolicyHe= lperLib/VariablePolicyHelperLib.inf + SortLib | MdeModulePkg/Library/UefiSortLib/Uefi= SortLib.inf FdtLib | EmbeddedPkg/Library/FdtLib/FdtLib.inf + PciPcdProducerLib | OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtP= ciPcdProducerLib.inf + PciSegmentLib | MdePkg/Library/BasePciSegmentLibPci/B= asePciSegmentLibPci.inf + PciHostBridgeLib | OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPc= iHostBridgeLib.inf + PciHostBridgeUtilityLib | ArmVirtPkg/Library/ArmVirtPciHostBrid= geUtilityLib/ArmVirtPciHostBridgeUtilityLib.inf + MmuLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/MmuLib/MmuBaseLib.inf + FileExplorerLib | MdeModulePkg/Library/FileExplorerLib/= FileExplorerLib.inf + +!if $(HTTP_BOOT_ENABLE) =3D=3D TRUE + HttpLib | MdeModulePkg/Library/DxeHttpLib/DxeHt= tpLib.inf +!endif + UefiBootManagerLib | MdeModulePkg/Library/UefiBootManagerL= ib/UefiBootManagerLib.inf + OrderedCollectionLib | MdePkg/Library/BaseOrderedCollectionR= edBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + ReportStatusCodeLib | MdePkg/Library/BaseReportStatusCodeLi= bNull/BaseReportStatusCodeLibNull.inf + + PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPoin= tLib/BasePeCoffGetEntryPointLib.inf PeCoffExtraActionLib | MdePkg/Library/BasePeCoffExtraActionL= ibNull/BasePeCoffExtraActionLibNull.inf DebugAgentLib | MdeModulePkg/Library/DebugAgentLibNul= l/DebugAgentLibNull.inf + CpuExceptionHandlerLib | MdeModulePkg/Library/CpuExceptionHand= lerLibNull/CpuExceptionHandlerLibNull.inf + + PlatformBootManagerLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/PlatformBootManagerLib/PlatformBootManagerLib.inf + BootLogoLib | MdeModulePkg/Library/BootLogoLib/Boot= LogoLib.inf + QemuBootOrderLib | OvmfPkg/Library/QemuBootOrderLib/Qemu= BootOrderLib.inf + QemuFwCfgSimpleParserLib | OvmfPkg/Library/QemuFwCfgSimpleParser= Lib/QemuFwCfgSimpleParserLib.inf + QemuLoadImageLib | OvmfPkg/Library/GenericQemuLoadImageL= ib/GenericQemuLoadImageLib.inf + + # + # Virtio Support + # + VirtioLib | OvmfPkg/Library/VirtioLib/VirtioLib.i= nf + FrameBufferBltLib | MdeModulePkg/Library/FrameBufferBltLi= b/FrameBufferBltLib.inf + QemuFwCfgLib | OvmfPkg/Library/QemuFwCfgLib/QemuFwCf= gLibMmio.inf =20 DebugLib | MdePkg/Library/BaseDebugLibSerialPort= /BaseDebugLibSerialPort.inf =20 @@ -91,7 +188,7 @@ ReportStatusCodeLib | MdeModulePkg/Library/PeiReportStatusC= odeLib/PeiReportStatusCodeLib.inf OemHookStatusCodeLib | MdeModulePkg/Library/OemHookStatusCod= eLibNull/OemHookStatusCodeLibNull.inf PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPoin= tLib/BasePeCoffGetEntryPointLib.inf - QemuFwCfgLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/QemuFwCfgLib/QemuFwCfgLib.inf + QemuFwCfgLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/QemuFwCfgLib/QemuFwCfgPeiLib.inf MmuLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/MmuLib/MmuBaseLibPei.inf =20 [LibraryClasses.common.PEIM] @@ -106,9 +203,59 @@ ExtractGuidedSectionLib | MdePkg/Library/PeiExtractGuidedSectio= nLib/PeiExtractGuidedSectionLib.inf PcdLib | MdePkg/Library/PeiPcdLib/PeiPcdLib.inf QemuFwCfgS3Lib | OvmfPkg/Library/QemuFwCfgS3Lib/PeiQem= uFwCfgS3LibFwCfg.inf - QemuFwCfgLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/QemuFwCfgLib/QemuFwCfgLib.inf + QemuFwCfgLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/QemuFwCfgLib/QemuFwCfgPeiLib.inf =20 MmuLib | Platform/Loongson/LoongArchQemuPkg/Librar= y/MmuLib/MmuBaseLibPei.inf +[LibraryClasses.common.DXE_CORE] + HobLib | MdePkg/Library/DxeCoreHobLib/DxeCoreH= obLib.inf + DxeCoreEntryPoint | MdePkg/Library/DxeCoreEntryPoint/DxeC= oreEntryPoint.inf + MemoryAllocationLib | MdeModulePkg/Library/DxeCoreMemoryAll= ocationLib/DxeCoreMemoryAllocationLib.inf + ReportStatusCodeLib | MdeModulePkg/Library/DxeReportStatusC= odeLib/DxeReportStatusCodeLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + PcdLib | MdePkg/Library/DxePcdLib/DxePcdLib.inf + HobLib | MdePkg/Library/DxeHobLib/DxeHobLib.inf + DxeCoreEntryPoint | MdePkg/Library/DxeCoreEntryPoint/DxeC= oreEntryPoint.inf + MemoryAllocationLib | MdePkg/Library/UefiMemoryAllocationLi= b/UefiMemoryAllocationLib.inf + ReportStatusCodeLib | MdeModulePkg/Library/RuntimeDxeReport= StatusCodeLib/RuntimeDxeReportStatusCodeLib.inf + UefiRuntimeLib | MdePkg/Library/UefiRuntimeLib/UefiRun= timeLib.inf + ExtractGuidedSectionLib | MdePkg/Library/PeiExtractGuidedSectio= nLib/PeiExtractGuidedSectionLib.inf + QemuFwCfgS3Lib | OvmfPkg/Library/QemuFwCfgS3Lib/DxeQem= uFwCfgS3LibFwCfg.inf + RealTimeClockLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/LsRealTimeClockLib/LsRealTimeClockLib.inf + VariablePolicyLib | MdeModulePkg/Library/VariablePolicyLi= b/VariablePolicyLibRuntimeDxe.inf + QemuFwCfgLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/QemuFwCfgLib/QemuFwCfgPeiLib.inf + EfiResetSystemLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf + ResetSystemLib | Platform/Loongson/LoongArchQemuPkg/Li= brary/ResetSystemAcpiLib/DxeResetSystemAcpiGedLib.inf +!if $(TARGET) !=3D RELEASE + DebugLib | MdePkg/Library/DxeRuntimeDebugLibSeri= alPort/DxeRuntimeDebugLibSerialPort.inf +!endif + +[LibraryClasses.common.UEFI_DRIVER] + PcdLib | MdePkg/Library/DxePcdLib/DxePcdLib.inf + HobLib | MdePkg/Library/DxeHobLib/DxeHobLib.inf + DxeCoreEntryPoint | MdePkg/Library/DxeCoreEntryPoint/DxeC= oreEntryPoint.inf + MemoryAllocationLib | MdePkg/Library/UefiMemoryAllocationLi= b/UefiMemoryAllocationLib.inf + ReportStatusCodeLib | MdeModulePkg/Library/DxeReportStatusC= odeLib/DxeReportStatusCodeLib.inf + UefiScsiLib | MdePkg/Library/UefiScsiLib/UefiScsiLi= b.inf + ExtractGuidedSectionLib | MdePkg/Library/PeiExtractGuidedSectio= nLib/PeiExtractGuidedSectionLib.inf + QemuFwCfgLib | OvmfPkg/Library/QemuFwCfgLib/QemuFwCf= gLibMmio.inf + +[LibraryClasses.common.DXE_DRIVER] + PcdLib | MdePkg/Library/DxePcdLib/DxePcdLib.inf + HobLib | MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib | MdePkg/Library/UefiMemoryAllocationLi= b/UefiMemoryAllocationLib.inf + ReportStatusCodeLib | MdeModulePkg/Library/DxeReportStatusC= odeLib/DxeReportStatusCodeLib.inf + UefiScsiLib | MdePkg/Library/UefiScsiLib/UefiScsiLi= b.inf + CpuExceptionHandlerLib | UefiCpuPkg/Library/CpuExceptionHandle= rLib/DxeCpuExceptionHandlerLib.inf + ExtractGuidedSectionLib | MdePkg/Library/DxeExtractGuidedSectio= nLib/DxeExtractGuidedSectionLib.inf + QemuFwCfgS3Lib | OvmfPkg/Library/QemuFwCfgS3Lib/DxeQem= uFwCfgS3LibFwCfg.inf + QemuFwCfgLib | OvmfPkg/Library/QemuFwCfgLib/QemuFwCf= gLibMmio.inf + +[LibraryClasses.common.UEFI_APPLICATION] + PcdLib | MdePkg/Library/DxePcdLib/DxePcdLib.inf + HobLib | MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib | MdePkg/Library/UefiMemoryAllocationLi= b/UefiMemoryAllocationLib.inf + ExtractGuidedSectionLib | MdePkg/Library/DxeExtractGuidedSectio= nLib/DxeExtractGuidedSectionLib.inf =20 =20 ##########################################################################= ###### @@ -116,12 +263,32 @@ # Pcd Section - list of all EDK II PCD Entries defined by this Platform. # ##########################################################################= ###### +[PcdsFeatureFlag] + gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport | F= ALSE +# gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial | T= RUE +# gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory | T= RUE + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress | T= RUE + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport | T= RUE + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport | F= ALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport | F= ALSE + gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation | T= RUE + gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation | T= RUE [PcdsFixedAtBuild] ## BaseLib ## gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength | 1= 000000 gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength | 1= 000000 gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength | 1= 000000 + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout | 1= 0000000 =20 + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize | 1 + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange | F= ALSE + gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler | 0= x10 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize | 0= x2000 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize | 0= x8000 + gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress | 0= x0 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize | 48 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize | 32 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask | 0= x07 gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel | 0= x8000004F # DEBUG_INIT 0x00000001 // Initialization # DEBUG_WARN 0x00000002 // Warnings @@ -168,6 +335,60 @@ # 0x90000000 - 0xA0000000 # gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop | 0= xA0000000 + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions | 0= x06 + + gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile | {= 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0x= f4, 0x66, 0x23, 0x31 } + + # + # Network Pcds + # +!include NetworkPkg/NetworkPcds.dsc.inc +##########################################################################= ###### +# +# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Pla= tform +# +##########################################################################= ###### +[PcdsDynamicDefault] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase | 0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 | 0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 | 0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase | 0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 | 0 + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved | 0 + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration | F= ALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution | 8= 00 + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution | 6= 00 + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut | 2 + + # Set video resolution for text setup. + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution | 6= 40 + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution | 4= 80 + + gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion | 0= x0300 + gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosDocRev | 0= x0 + + gLoongArchQemuPkgTokenSpaceGuid.PcdRamSize | 0= x40000000 + + ## If TRUE, OvmfPkg/AcpiPlatformDxe will not wait for PCI + # enumeration to complete before installing ACPI tables. + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration |TR= UE + gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation |0x0 + # set PcdPciExpressBaseAddress to MAX_UINT64, which signifies that this + # PCD and PcdPciDisableBusEnumeration above have not been assigned yet + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress |0x= FFFFFFFFFFFFFFFF + + # + # IPv4 and IPv6 PXE Boot support. + # + gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport | 0= x01 + gEfiNetworkPkgTokenSpaceGuid.PcdIPv6PXESupport | 0= x01 + + # + # SMBIOS entry point version + # + gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0300 + gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosDocRev|0x0 + gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated|TRUE =20 [Components] =20 @@ -195,3 +416,194 @@ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf } =20 + # + # DXE Phase modules + # + MdeModulePkg/Core/Dxe/DxeMain.inf { + + NULL | MdeModulePkg/Library/LzmaCustomDe= compressLib/LzmaCustomDecompressLib.inf + DevicePathLib | MdePkg/Library/UefiDevicePathLib/= UefiDevicePathLib.inf + ExtractGuidedSectionLib | MdePkg/Library/DxeExtractGuidedSe= ctionLib/DxeExtractGuidedSectionLib.inf + } + + MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCod= eRouterRuntimeDxe.inf + MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRun= timeDxe.inf + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntim= eDxe.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/TimerDxe.inf + MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf + MdeModulePkg/Universal/Metronome/Metronome.inf + EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + + # + # Variable + # +# Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntimeD= xe/FvbServicesRuntimeDxe.inf + OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf { + + PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.i= nf + } + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf { + + NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + } + + # + # Platform Driver + # + OvmfPkg/VirtioBlkDxe/VirtioBlk.inf + OvmfPkg/VirtioScsiDxe/VirtioScsi.inf + OvmfPkg/VirtioRngDxe/VirtioRng.inf + + # + # File system + # + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + FatPkg/EnhancedFatDxe/Fat.inf + + # + #BDS + # + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf { + + DevicePathLib | MdePkg/Library/UefiDevicePathLib/= UefiDevicePathLib.inf + PcdLib | MdePkg/Library/BasePcdLibNull/Bas= ePcdLibNull.inf + } + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + MdeModulePkg/Universal/BdsDxe/BdsDxe.inf + MdeModulePkg/Logo/LogoDxe.inf + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Application/UiApp/UiApp.inf { + + NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf + NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf + NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanc= eManagerUiLib.inf + } + + OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf { + + NULL|OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierLibNull.inf + } + + # + # Network Support + # +#!include NetworkPkg/NetworkComponents.dsc.inc + +# NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf { +# +# NULL|OvmfPkg/Library/PxeBcPcdProducerLib/PxeBcPcdProducerLib.inf +# } + +!if $(NETWORK_TLS_ENABLE) =3D=3D TRUE + NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf { + + NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf + } +!endif + OvmfPkg/VirtioNetDxe/VirtioNet.inf + + + # + # IDE/SCSI + # + OvmfPkg/SataControllerDxe/SataControllerDxe.inf + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + + # + # SMBIOS Support + # + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf { + + NULL | OvmfPkg/Library/SmbiosVersionLib/= DetectSmbiosVersionLib.inf + } + OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf + + # + # PCI + # + Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.inf + EmbeddedPkg/Drivers/FdtClientDxe/FdtClientDxe.inf + MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf + OvmfPkg/Virtio10Dxe/Virtio10.inf + + # + # Console + # + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + MdeModulePkg/Universal/PrintDxe/PrintDxe.inf + MdeModulePkg/Universal/SerialDxe/SerialDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf= { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + + # + # Video + # + OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf + OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + OvmfPkg/PlatformDxe/Platform.inf + + # + # Usb Support + # + MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf + MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # ACPI Support + # + MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsRes= ourceTableDxe.inf + OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf + + # + #app + # + ShellPkg/Application/Shell/Shell.inf { + + ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellComman= dLib.inf + NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2Comm= andsLib.inf + NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1Comm= andsLib.inf + NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3Comm= andsLib.inf + NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1Co= mmandsLib.inf + NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1Comm= andsLib.inf + NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1= CommandsLib.inf + NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1= CommandsLib.inf + HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandlePar= singLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcf= gCommandLib.inf + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000 + } diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.fdf index f964304fdc..ba2942e455 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf @@ -22,6 +22,15 @@ $(SECFV_OFFSET)|$(SECFV_SIZE) gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase|gLoongArchQemuPkgTokenSp= aceGuid.PcdFlashSecFvSize FV =3D SECFV =20 +$(PEIFV_OFFSET)|$(PEIFV_SIZE) +gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase|gLoongArchQemuPkgTokenSp= aceGuid.PcdFlashPeiFvSize +FV =3D PEIFV + +$(DXEFV_OFFSET)|$(DXEFV_SIZE) +gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvBase|gLoongArchQemuPkgTokenSp= aceGuid.PcdFlashDxeFvSize +FV =3D FVMAIN_COMPACT + +!include VarStore.fdf.inc ##########################################################################= ########################### [FV.SECFV] FvNameGuid =3D 587d4265-5e71-41da-9c35-4258551f1e22 @@ -78,6 +87,178 @@ INF MdeModulePkg/Core/Pei/PeiMain.inf INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf INF Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf +##########################################################################= ########################### +[FV.DXEFV] +FvNameGuid =3D 5d19a5b3-130f-459b-a292-9270a9e6bc62 +BlockSize =3D $(BLOCK_SIZE) +FvAlignment =3D 16 +ERASE_POLARITY =3D 1 +MEMORY_MAPPED =3D TRUE +STICKY_WRITE =3D TRUE +LOCK_CAP =3D TRUE +LOCK_STATUS =3D TRUE +READ_DISABLED_CAP =3D TRUE +READ_ENABLED_CAP =3D TRUE +READ_STATUS =3D TRUE +READ_LOCK_CAP =3D TRUE +READ_LOCK_STATUS =3D TRUE +WRITE_DISABLED_CAP =3D TRUE +WRITE_ENABLED_CAP =3D TRUE +WRITE_STATUS =3D TRUE +WRITE_LOCK_CAP =3D TRUE +WRITE_LOCK_STATUS =3D TRUE + +APRIORI DXE { + INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf +} + +# +# DXE Phase modules +# +INF MdeModulePkg/Core/Dxe/DxeMain.inf + +INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatus= CodeRouterRuntimeDxe.inf +INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandler= RuntimeDxe.inf +INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf +INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf +INF Platform/Loongson/LoongArchQemuPkg/Drivers/CpuDxe/CpuDxe.inf +INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf +INF Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/TimerDxe.inf +INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf +INF MdeModulePkg/Universal/Metronome/Metronome.inf +INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf +INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRun= timeDxe.inf +INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf +INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + +# +# Variable +# +INF Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntim= eDxe/FvbServicesRuntimeDxe.inf +INF OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf +INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf +# +# PCI +# +INF Platform/Loongson/LoongArchQemuPkg/Drivers/PciCpuIo2Dxe/PciCpuIo2Dxe.= inf +INF EmbeddedPkg/Drivers/FdtClientDxe/FdtClientDxe.inf +INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf +INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf +INF OvmfPkg/Virtio10Dxe/Virtio10.inf + +# +# Platform Driver +# +INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf +INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf +INF OvmfPkg/VirtioRngDxe/VirtioRng.inf +INF OvmfPkg/VirtioNetDxe/VirtioNet.inf + +# +# Console +# +INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf +INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf +INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +INF MdeModulePkg/Universal/PrintDxe/PrintDxe.inf +INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf +INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.= inf + +# +#Video +# +INF OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf +INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf +INF OvmfPkg/PlatformDxe/Platform.inf + +# +# IDE +# +INF OvmfPkg/SataControllerDxe/SataControllerDxe.inf +INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf +INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf +INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + +# +# Usb Support +# +INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf +INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf +INF MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf +INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf +INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf +INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + +# +#BDS +# +INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf +INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf +INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf +INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf +INF MdeModulePkg/Logo/LogoDxe.inf +INF MdeModulePkg/Application/UiApp/UiApp.inf +INF OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf +# +#Smbios +# +INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf +INF OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf + +# +#Acpi +# +INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf +INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphics= ResourceTableDxe.inf +INF OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf + +# +# Network modules +#!include NetworkPkg/Network.fdf.inc + +# +# File system +# +INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf +INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf +INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf +INF FatPkg/EnhancedFatDxe/Fat.inf + +# +#Boot OS +# +INF ShellPkg/Application/Shell/Shell.inf + +##########################################################################= ########################### +[FV.FVMAIN_COMPACT] +FvNameGuid =3D af8c3fe8-9ce8-4548-884a-e3f4dd91f040 +FvAlignment =3D 16 +ERASE_POLARITY =3D 1 +MEMORY_MAPPED =3D TRUE +STICKY_WRITE =3D TRUE +LOCK_CAP =3D TRUE +LOCK_STATUS =3D TRUE +WRITE_DISABLED_CAP =3D TRUE +WRITE_ENABLED_CAP =3D TRUE +WRITE_STATUS =3D TRUE +WRITE_LOCK_CAP =3D TRUE +WRITE_LOCK_STATUS =3D TRUE +READ_DISABLED_CAP =3D TRUE +READ_ENABLED_CAP =3D TRUE +READ_STATUS =3D TRUE +READ_LOCK_CAP =3D TRUE +READ_LOCK_STATUS =3D TRUE + +FILE FV_IMAGE =3D 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { + SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED= =3D TRUE { + SECTION FV_IMAGE =3D DXEFV + } + } =20 ##########################################################################= ########################### [Rule.Common.SEC] @@ -102,3 +283,65 @@ INF Platform/Loongson/LoongArchQemuPkg/PlatformPei/Pl= atformPei.inf } =20 ##########################################################################= ########################### +[Rule.Common.DXE_CORE] + FILE DXE_CORE =3D $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING=3D"$(MODULE_NAME)" Optional + } + +##########################################################################= ########################### +[Rule.Common.DXE_DRIVER] + FILE DRIVER =3D $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING=3D"$(MODULE_NAME)" Optional + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + +##########################################################################= ########################### +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER =3D $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING=3D"$(MODULE_NAME)" Optional + } + +##########################################################################= ########################### +[Rule.Common.UEFI_DRIVER] + FILE DRIVER =3D $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING=3D"$(MODULE_NAME)" Optional + } + +##########################################################################= ########################### +[Rule.Common.UEFI_DRIVER.BINARY] + FILE DRIVER =3D $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING=3D"$(MODULE_NAME)" Optional + VERSION STRING=3D"$(INF_VERSION)" Optional BUILD_NUM=3D$(BUILD_NUMBE= R) + } + +##########################################################################= ########################### +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION =3D $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING=3D"$(MODULE_NAME)" Optional + } + +##########################################################################= ########################### +[Rule.Common.UEFI_APPLICATION.BINARY] + FILE APPLICATION =3D $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING=3D"$(MODULE_NAME)" Optional + VERSION STRING=3D"$(INF_VERSION)" Optional BUILD_NUM=3D$(BUILD_NUMBE= R) + } + +##########################################################################= ########################### +[Rule.Common.USER_DEFINED.ACPITABLE] + FILE FREEFORM =3D $(NAMED_GUID) { + RAW ACPI |.acpi + RAW ASL |.aml + } diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc b/Platform= /Loongson/LoongArchQemuPkg/Loongson.fdf.inc index a1a2d537e3..964d69ed44 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc @@ -19,3 +19,45 @@ DEFINE FD_SIZE =3D 0x400000 #Set Sec base address and size in flash DEFINE SECFV_OFFSET =3D 0x00000000 DEFINE SECFV_SIZE =3D 0x00010000 + +#Set Pei base address and size in flash +DEFINE PEIFV_OFFSET =3D 0x00010000 +DEFINE PEIFV_SIZE =3D 0x00040000 + +#Set Dxe base address and size in flash +DEFINE DXEFV_OFFSET =3D 0x00050000 +DEFINE DXEFV_SIZE =3D 0x00350000 + +#Set Var base address and size in flash +DEFINE VARIABLE_OFFSET =3D 0x003a0000 +DEFINE VAR_ALL_SIZE =3D 0x60000 + +##########################################################################= ## +#Set Var Flash layout +DEFINE VARIABLE_SIZE =3D 0x00010000 +DEFINE VAR_ALL_BLOCKS =3D 0x60 + +DEFINE RESERVE1_OFFSET =3D $(VARIABLE_OFFSET) + $(VARIABLE_SIZE) +DEFINE RESERVE1_SIZE =3D 0xB000 + +DEFINE RESERVE2_OFFSET =3D $(RESERVE1_OFFSET) + $(RESERVE1_SIZE) +DEFINE RESERVE2_SIZE =3D 0x14000 + +DEFINE SPARE_OFFSET =3D $(RESERVE2_OFFSET) + $(RESERVE2_SIZE) +DEFINE SPARE_SIZE =3D 0x20000 + +DEFINE FWTWORKING_OFFSET =3D $(SPARE_OFFSET) + $(SPARE_SIZE) +DEFINE FWTWORKING_SIZE =3D 0x8000 + +DEFINE EVENT_LOG_OFFSET =3D $(FWTWORKING_OFFSET) + $(FWTWORKING_= SIZE) +DEFINE EVENT_LOG_SIZE =3D 0x8000 + +# Set Variable +SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 =3D 0 +SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize =3D $(VAR= IABLE_SIZE) + +# Set FtwSpare +SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize =3D $(SPA= RE_SIZE) + +# Set FtwWorking +SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize =3D $(F= WTWORKING_SIZE) diff --git a/Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc b/Platform= /Loongson/LoongArchQemuPkg/VarStore.fdf.inc new file mode 100644 index 0000000000..625fa23543 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc @@ -0,0 +1,64 @@ +## @file +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +$(VARIABLE_OFFSET)|$(VARIABLE_SIZE) +#NV_VARIABLE_STORE +DATA =3D { + #jmp to 0x1c060000 + 0x01, 0x0c, 0x38, 0x14, 0x21, 0x00, 0x80, 0x03, + 0x21, 0x00, 0x00, 0x4c, 0x00, 0x10, 0x14, 0x00, + # FileSystemGuid: gEfiSystemNvDataFvGuid =3D + # { 0xFFF12B8D, 0x7696, 0x4C8B, + # { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }} + 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, + 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50, + # FvLength: 0x60000 + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + # Signature "_FVH" # Attributes + 0x5f, 0x46, 0x56, 0x48, 0x36, 0x0c, 0x04, 0x00, + # HeaderLength # CheckSum # ExtHeaderOffset #Reserved #Revision + 0x48, 0x00, 0x8F, 0x6B, 0x00, 0x00, 0x00, 0x02, + # Blockmap[0]: 0x10 Blocks * 0x1000 Bytes / Block + 0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + # Blockmap[1]: End + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ## This is the VARIABLE_STORE_HEADER + # gEfiVariableGuid =3D {0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, = 0x85, 0x70, 0x7f, 0xfe, 0x7d}} + 0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41, + 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d, + # Size: 0x10000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariabl= eSize) - + # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) =3D 0xffb8 + # This can speed up the Variable Dispatch a bit. + 0xb8, 0xff, 0x00, 0x00, + # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32 + 0x5a, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} +$(RESERVE1_OFFSET)|$(RESERVE1_SIZE) +#NV_RESERVE1_STORE + +$(RESERVE2_OFFSET)|$(RESERVE2_SIZE) +#NV_RESERVE2_STORE + +$(SPARE_OFFSET)|$(SPARE_SIZE) +#NV_FTW_SPARE + +$(FWTWORKING_OFFSET)|$(FWTWORKING_SIZE) +#NV_FTW_WORKING +DATA =3D { + # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature =3D gEdkiiWorkingBl= ockSignatureGuid =3D + # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0= x1b, 0x95 }} + 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49, + 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95, + # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Res= erved + 0x07, 0x7f, 0x44, 0x88, 0xfe, 0xff, 0xff, 0xff, + # WriteQueueSize: UINT64 #Size:0x8000 - 0x20(FTW_WORKING_HEADER) =3D 0x7= FE0 + 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +$(EVENT_LOG_OFFSET)|$(EVENT_LOG_SIZE) +#NV_EVENT_LOG --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93898): https://edk2.groups.io/g/devel/message/93898 Mute This Topic: https://groups.io/mt/93715817/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93896+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93896+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299410; cv=none; d=zohomail.com; s=zohoarc; b=YbBSyHN6kbudNgvR8tBhXG59LoR/FhV4fjRSPU6V2quDBYkGCsjf+t/OW1PccI+8tLESzjWam9zoRBtArzXqlwnWutx7eWJavtepGqTFGg7PxnESGdfzoK7lr1A098MEBqdUY1xbKEHgcuQ3cSSO5n9CAJSwyE3218kLK2oZxBE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299410; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=uU/VabDi11pn4eYoWCyR1ZLjBfvcgaDpW7SJPvBKwKs=; b=TIlY9gW7xlliuWCLjRgY9i5t4bueJAMB8+P5HLAmawt1Mu+woMeyRMuuDuLj1UBmUuWe7Sp+ZIeukEuKhoc9+bZKjhSC+2sCg3+ivfCfJEKXsCbwLlDtsrhGWSvPI50dpALFMuWF0l/19PD4QD0jYwqOxoyvWeG5daA8JIcTkGs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93896+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299410567777.4400721527353; Thu, 15 Sep 2022 20:36:50 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id Q3HeYY1788612x68kHw6JKZT; Thu, 15 Sep 2022 20:36:49 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web09.2233.1663299407662309031 for ; Thu, 15 Sep 2022 20:36:48 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S17; Fri, 16 Sep 2022 11:36:45 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 15/16] Platform/Loongson: Add QemuFlashFvbServicesRuntimeDxe driver. Date: Fri, 16 Sep 2022 11:36:32 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S17 X-Coremail-Antispam: 1UD129KBjvAXoWDXryxCr48Zr1UJw47AF13Jwb_yoW7WFWDGo WxtFyIkw18tw1kZryrGryqk3yjqFyrWFsaqr4rZr9Fy3Z5Jwn0kFZav3W5W393tw18Jrnx J3yrXr93AF43J3s5n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: dToO1X5ZuD3FeefPEEctzJALx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299409; bh=RJsTSzQwROj5W/utkfksgnzK8eDWYzfEN4d7EuqZppk=; h=Cc:Date:From:Reply-To:Subject:To; b=WKQbmOcW1fL0AsSNjAbI3fY3FjeK08ULDz8dPUrxMf8zXztlidFQHHcLy8Wvmai60BC GZsYZyPK9XOIMCjzwcdBj5yXuCXoi6zaMnt1i5+rZEvagFd0ihhEcpOJQcS/51M9Dg3Cl nY4V0HlCMWgxwT3p0ynPyiGAtJwLmJXtqGw= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299412398100040 Content-Type: text/plain; charset="utf-8" This library provides flash read and write functionality and supports writing variables to flash. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../QemuFlashFvbServicesRuntimeDxe/FvbInfo.c | 115 ++ .../FvbServicesRuntimeDxe.inf | 73 ++ .../FwBlockService.c | 1158 +++++++++++++++++ .../FwBlockService.h | 178 +++ .../FwBlockServiceDxe.c | 152 +++ .../QemuFlash.c | 251 ++++ .../QemuFlash.h | 86 ++ .../QemuFlashDxe.c | 21 + .../Loongson/LoongArchQemuPkg/Loongson.dsc | 4 +- 9 files changed, 2036 insertions(+), 2 deletions(-) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvb= ServicesRuntimeDxe/FvbInfo.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvb= ServicesRuntimeDxe/FvbServicesRuntimeDxe.inf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvb= ServicesRuntimeDxe/FwBlockService.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvb= ServicesRuntimeDxe/FwBlockService.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvb= ServicesRuntimeDxe/FwBlockServiceDxe.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvb= ServicesRuntimeDxe/QemuFlash.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvb= ServicesRuntimeDxe/QemuFlash.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvb= ServicesRuntimeDxe/QemuFlashDxe.c diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbService= sRuntimeDxe/FvbInfo.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlas= hFvbServicesRuntimeDxe/FvbInfo.c new file mode 100644 index 0000000000..df772f72be --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntim= eDxe/FvbInfo.c @@ -0,0 +1,115 @@ +/** @file + Defines data structure that is the volume header found.These data is int= ent + to decouple FVB driver with FV header. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +// +// The package level header files this module uses +// +#include + +// +// The protocols, PPI and GUID definitions for this module +// +#include +// +// The Library classes this module consumes +// +#include +#include + +typedef struct { + UINT64 FvLength; + EFI_FIRMWARE_VOLUME_HEADER FvbInfo; + // + // EFI_FV_BLOCK_MAP_ENTRY ExtraBlockMap[n];//n=3D0 + // + EFI_FV_BLOCK_MAP_ENTRY End[1]; +} EFI_FVB_MEDIA_INFO; + +EFI_FVB_MEDIA_INFO mPlatformFvbMediaInfo[] =3D { + // + // System NvStorage FVB + // + { + FixedPcdGet32 (PcdAllVarSize), + { + { + 0, + }, // ZeroVector[16] + EFI_SYSTEM_NV_DATA_FV_GUID, + FixedPcdGet32 (PcdAllVarSize), + EFI_FVH_SIGNATURE, + EFI_FVB2_MEMORY_MAPPED | + EFI_FVB2_READ_ENABLED_CAP | + EFI_FVB2_READ_STATUS | + EFI_FVB2_WRITE_ENABLED_CAP | + EFI_FVB2_WRITE_STATUS | + EFI_FVB2_ERASE_POLARITY | + EFI_FVB2_ALIGNMENT_16, + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY= ), + 0, // CheckSum + 0, // ExtHeaderOffset + { + 0, + }, // Reserved[1] + 2, // Revision + { + { + (FixedPcdGet32 (PcdAllVarSize))/ + FixedPcdGet32 (PcdFlashBlockSize), + FixedPcdGet32 (PcdFlashBlockSize), + } + } // BlockMap[1] + }, + { + { + 0, + 0 + } + } // End[1] + } +}; + +EFI_STATUS +GetFvbInfo ( + IN UINT64 FvLength, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ) +{ + STATIC BOOLEAN Checksummed =3D FALSE; + UINTN Index; + + if (!Checksummed) { + for (Index =3D 0; + Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_IN= FO); + Index +=3D 1) + { + UINT16 Checksum; + mPlatformFvbMediaInfo[Index].FvbInfo.Checksum =3D 0; + Checksum =3D CalculateCheckSum1= 6 ( + (UINT16 *)&mPlatfo= rmFvbMediaInfo[Index].FvbInfo, + mPlatformFvbMediaI= nfo[Index].FvbInfo.HeaderLength + ); + mPlatformFvbMediaInfo[Index].FvbInfo.Checksum =3D Checksum; + } + Checksummed =3D TRUE; + } + + for (Index =3D 0; + Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO= ); + Index +=3D 1) + { + if (mPlatformFvbMediaInfo[Index].FvLength =3D=3D FvLength) { + *FvbInfo =3D &mPlatformFvbMediaInfo[Index].FvbInfo; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbService= sRuntimeDxe/FvbServicesRuntimeDxe.inf b/Platform/Loongson/LoongArchQemuPkg/= Drivers/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf new file mode 100644 index 0000000000..4b0c42b075 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntim= eDxe/FvbServicesRuntimeDxe.inf @@ -0,0 +1,73 @@ +## @file +# Component description file for Emu Fimware Volume Block DXE driver modul= e. +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D FvbServicesRuntimeDxe + FILE_GUID =3D 733cbac2-b23f-4b92-bc8e-fb01ce5907b7 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D FvbInitialize + +# +# The following information is for reference only and not required by the = build +# tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources] + FvbInfo.c + FwBlockService.c + FwBlockServiceDxe.c + QemuFlash.c + QemuFlashDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + DxeServicesTableLib + MemoryAllocationLib + PcdLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeLib + +[Guids] + gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED + # gEfiEventVirtualAddressChangeGuid # Create Event: EVENT_GROUP_GUID + +[Protocols] + gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL SOMETIMES_PRODU= CED + gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_PRODU= CED + +[FixedPcd] + gLoongArchQemuPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase + gLoongArchQemuPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase + gLoongArchQemuPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashFdBase + gLoongArchQemuPkgTokenSpaceGuid.PcdAllVarSize + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashBlockSize +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 + +[Depex] + TRUE diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbService= sRuntimeDxe/FwBlockService.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/Q= emuFlashFvbServicesRuntimeDxe/FwBlockService.c new file mode 100644 index 0000000000..d44f2b460c --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntim= eDxe/FwBlockService.c @@ -0,0 +1,1158 @@ +/** @file + Implementations for Firmware Volume Block protocol. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +// +// The protocols, PPI and GUID definitions for this module +// +#include +#include + +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include + +#include "FwBlockService.h" +#include "QemuFlash.h" + +#define EFI_FVB2_STATUS \ + (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_ST= ATUS) + +ESAL_FWB_GLOBAL *mFvbModuleGlobal; + +FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate =3D { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { + (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), + (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) + } + }, + EfiMemoryMappedIO, + (EFI_PHYSICAL_ADDRESS)0, + (EFI_PHYSICAL_ADDRESS)0, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate =3D { + { + { + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_VOL_DP, + { + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) + } + }, + { 0 } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate =3D { + FVB_DEVICE_SIGNATURE, + NULL, + 0, + { + FvbProtocolGetAttributes, + FvbProtocolSetAttributes, + FvbProtocolGetPhysicalAddress, + FvbProtocolGetBlockSize, + FvbProtocolRead, + FvbProtocolWrite, + FvbProtocolEraseBlocks, + NULL + } +}; + + +EFI_STATUS +GetFvbInstance ( + IN UINTN Instance, + IN ESAL_FWB_GLOBAL *Global, + OUT EFI_FW_VOL_INSTANCE **FwhInstance + ) +/*++ + + Routine Description: + Retrieves the physical address of a memory mapped FV + + Arguments: + Instance - The FV instance whose base address is going to= be + returned + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + FwhInstance - The EFI_FW_VOL_INSTANCE firmware instance stru= cture + + Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhRecord; + + *FwhInstance =3D NULL; + if (Instance >=3D Global->NumFv) { + return EFI_INVALID_PARAMETER; + } + // + // Find the right instance of the FVB private data + // + FwhRecord =3D Global->FvInstance; + while (Instance > 0) { + FwhRecord =3D (EFI_FW_VOL_INSTANCE *) + ( + (UINTN)((UINT8 *)FwhRecord) + FwhRecord->VolumeHeader.Hea= derLength + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLU= ME_HEADER)) + ); + Instance--; + } + + *FwhInstance =3D FwhRecord; + + return EFI_SUCCESS; +} + +EFI_STATUS +FvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *Address, + IN ESAL_FWB_GLOBAL *Global + ) +/*++ + + Routine Description: + Retrieves the physical address of a memory mapped FV + + Arguments: + Instance - The FV instance whose base address is going to= be + returned + Address - Pointer to a caller allocated EFI_PHYSICAL_ADD= RESS + that on successful return, contains the base + address of the firmware volume. + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + + Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status =3D GetFvbInstance (Instance, Global, &FwhInstance); + ASSERT_EFI_ERROR (Status); + *Address =3D FwhInstance->FvBase; + + return EFI_SUCCESS; +} + +EFI_STATUS +FvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes, + IN ESAL_FWB_GLOBAL *Global + ) +/*++ + + Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, ret= urns + resulting attributes in output parameter + + Arguments: + Instance - The FV instance whose attributes is going to be + returned + Attributes - Output buffer which contains attributes + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + + Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status =3D GetFvbInstance (Instance, Global, &FwhInstance); + ASSERT_EFI_ERROR (Status); + *Attributes =3D FwhInstance->VolumeHeader.Attributes; + + return EFI_SUCCESS; +} + +EFI_STATUS +FvbGetLbaAddress ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks, + IN ESAL_FWB_GLOBAL *Global + ) +/*++ + + Routine Description: + Retrieves the starting address of an LBA in an FV + + Arguments: + Instance - The FV instance which the Lba belongs to + Lba - The logical block address + LbaAddress - On output, contains the physical starting addr= ess + of the Lba + LbaLength - On output, contains the length of the block + NumOfBlocks - A pointer to a caller allocated UINTN in which= the + number of consecutive blocks starting with Lba= is + returned. All blocks in this range have a size= of + BlockSize + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + + Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + UINT32 NumBlocks; + UINT32 BlockLength; + UINTN Offset; + EFI_LBA StartLba; + EFI_LBA NextLba; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status =3D GetFvbInstance (Instance, Global, &FwhInstance); + ASSERT_EFI_ERROR (Status); + + StartLba =3D 0; + Offset =3D 0; + BlockMap =3D &(FwhInstance->VolumeHeader.BlockMap[0]); + + // + // Parse the blockmap of the FV to find which map entry the Lba belongs = to + // + while (TRUE) { + NumBlocks =3D BlockMap->NumBlocks; + BlockLength =3D BlockMap->Length; + + if ((NumBlocks =3D=3D 0) || (BlockLength =3D=3D 0)) { + return EFI_INVALID_PARAMETER; + } + + NextLba =3D StartLba + NumBlocks; + + // + // The map entry found + // + if ((Lba >=3D StartLba) && (Lba < NextLba)) { + Offset =3D Offset + (UINTN)MultU64x32 ((Lba - StartLba), BlockLength= ); + if (LbaAddress !=3D NULL) { + *LbaAddress =3D FwhInstance->FvBase + Offset; + } + + if (LbaLength !=3D NULL) { + *LbaLength =3D BlockLength; + } + + if (NumOfBlocks !=3D NULL) { + *NumOfBlocks =3D (UINTN)(NextLba - Lba); + } + + return EFI_SUCCESS; + } + + StartLba =3D NextLba; + Offset =3D Offset + NumBlocks * BlockLength; + BlockMap++; + } +} + +EFI_STATUS +FvbSetVolumeAttributes ( + IN UINTN Instance, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes, + IN ESAL_FWB_GLOBAL *Global + ) +/*++ + + Routine Description: + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + + Arguments: + Instance - The FV instance whose attributes is going to be + modified + Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTE= S_2 + containing the desired firmware volume setting= s. + On successful return, it contains the new sett= ings + of the firmware volume + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + + Returns: + EFI_SUCCESS - Successfully returns + EFI_ACCESS_DENIED - The volume setting is locked and cannot be mod= ified + EFI_INVALID_PARAMETER - Instance not found, or The attributes requeste= d are + in conflict with the capabilities as declared = in + the firmware volume header + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FVB_ATTRIBUTES_2 OldAttributes; + EFI_FVB_ATTRIBUTES_2 *AttribPtr; + UINT32 Capabilities; + UINT32 OldStatus; + UINT32 NewStatus; + EFI_STATUS Status; + EFI_FVB_ATTRIBUTES_2 UnchangedAttributes; + + // + // Find the right instance of the FVB private data + // + Status =3D GetFvbInstance (Instance, Global, &FwhInstance); + ASSERT_EFI_ERROR (Status); + + AttribPtr =3D + (EFI_FVB_ATTRIBUTES_2 *)&(FwhInstance->VolumeHeader.Attributes); + OldAttributes =3D *AttribPtr; + Capabilities =3D OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \ + EFI_FVB2_READ_ENABLED_CAP | \ + EFI_FVB2_WRITE_DISABLED_CAP | \ + EFI_FVB2_WRITE_ENABLED_CAP | \ + EFI_FVB2_LOCK_CAP \ + ); + OldStatus =3D OldAttributes & EFI_FVB2_STATUS; + NewStatus =3D *Attributes & EFI_FVB2_STATUS; + + UnchangedAttributes =3D EFI_FVB2_READ_DISABLED_CAP | \ + EFI_FVB2_READ_ENABLED_CAP | \ + EFI_FVB2_WRITE_DISABLED_CAP | \ + EFI_FVB2_WRITE_ENABLED_CAP | \ + EFI_FVB2_LOCK_CAP | \ + EFI_FVB2_STICKY_WRITE | \ + EFI_FVB2_MEMORY_MAPPED | \ + EFI_FVB2_ERASE_POLARITY | \ + EFI_FVB2_READ_LOCK_CAP | \ + EFI_FVB2_WRITE_LOCK_CAP | \ + EFI_FVB2_ALIGNMENT; + + // + // Some attributes of FV is read only can *not* be set + // + if ((OldAttributes & UnchangedAttributes) ^ + (*Attributes & UnchangedAttributes)) + { + return EFI_INVALID_PARAMETER; + } + // + // If firmware volume is locked, no status bit can be updated + // + if (OldAttributes & EFI_FVB2_LOCK_STATUS) { + if (OldStatus ^ NewStatus) { + return EFI_ACCESS_DENIED; + } + } + // + // Test read disable + // + if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) =3D=3D 0) { + if ((NewStatus & EFI_FVB2_READ_STATUS) =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test read enable + // + if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) =3D=3D 0) { + if (NewStatus & EFI_FVB2_READ_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test write disable + // + if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) =3D=3D 0) { + if ((NewStatus & EFI_FVB2_WRITE_STATUS) =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test write enable + // + if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) =3D=3D 0) { + if (NewStatus & EFI_FVB2_WRITE_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test lock + // + if ((Capabilities & EFI_FVB2_LOCK_CAP) =3D=3D 0) { + if (NewStatus & EFI_FVB2_LOCK_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + *AttribPtr =3D (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); + *AttribPtr =3D (*AttribPtr) | NewStatus; + *Attributes =3D *AttribPtr; + + return EFI_SUCCESS; +} + +// +// FVB protocol APIs +// +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +/*++ + + Routine Description: + + Retrieves the physical address of the device. + + Arguments: + + This - Calling context + Address - Output buffer containing the address. + + Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + + return FvbGetPhysicalAddress ( + FvbDevice->Instance, + Address, + mFvbModuleGlobal + ); +} + +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +/*++ + + Routine Description: + Retrieve the size of a logical block + + Arguments: + This - Calling context + Lba - Indicates which block to return the size for. + BlockSize - A pointer to a caller allocated UINTN in which + the size of the block is returned + NumOfBlocks - a pointer to a caller allocated UINTN in which= the + number of consecutive blocks starting with Lba= is + returned. All blocks in this range have a size= of + BlockSize + + Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + + return FvbGetLbaAddress ( + FvbDevice->Instance, + Lba, + NULL, + BlockSize, + NumOfBlocks, + mFvbModuleGlobal + ); +} + +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +/*++ + + Routine Description: + Retrieves Volume attributes. No polarity translations are done. + + Arguments: + This - Calling context + Attributes - output buffer which contains attributes + + Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + + return FvbGetVolumeAttributes ( + FvbDevice->Instance, + Attributes, + mFvbModuleGlobal + ); +} + +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +/*++ + + Routine Description: + Sets Volume attributes. No polarity translations are done. + + Arguments: + This - Calling context + Attributes - output buffer which contains attributes + + Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + + return FvbSetVolumeAttributes ( + FvbDevice->Instance, + Attributes, + mFvbModuleGlobal + ); +} + +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +/*++ + + Routine Description: + + The EraseBlock() function erases one or more blocks as denoted by the + variable argument list. The entire parameter list of blocks must be + verified prior to erasing any blocks. If a block is requested that do= es + not exist within the associated firmware volume (it has a larger index= than + the last block of the firmware volume), the EraseBlock() function must + return EFI_INVALID_PARAMETER without modifying the contents of the fir= mware + volume. + + Arguments: + This - Calling context + ... - Starting LBA followed by Number of Lba to eras= e. + a -1 to terminate the list. + + Returns: + EFI_SUCCESS - The erase request was successfully completed + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled st= ate + EFI_DEVICE_ERROR - The block device is not functioning correctly = and + could not be written. Firmware device may have= been + partially erased + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN NumOfBlocks; + VA_LIST args; + EFI_LBA StartingLba; + UINTN NumOfLba; + EFI_STATUS Status; + + FvbDevice =3D FVB_DEVICE_FROM_THIS (This); + + Status =3D GetFvbInstance ( + FvbDevice->Instance, + mFvbModuleGlobal, + &FwhInstance + ); + ASSERT_EFI_ERROR (Status); + + NumOfBlocks =3D FwhInstance->NumOfBlocks; + + VA_START (args, This); + + do { + StartingLba =3D VA_ARG (args, EFI_LBA); + if (StartingLba =3D=3D EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba =3D VA_ARG (args, UINTN); + + // + // Check input parameters + // + if ((NumOfLba =3D=3D 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) { + VA_END (args); + return EFI_INVALID_PARAMETER; + } + } while (1); + + VA_END (args); + + VA_START (args, This); + do { + StartingLba =3D VA_ARG (args, EFI_LBA); + if (StartingLba =3D=3D EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba =3D VA_ARG (args, UINTN); + + while (NumOfLba > 0) { + Status =3D QemuFlashEraseBlock (StartingLba); + if (EFI_ERROR (Status)) { + VA_END (args); + return Status; + } + + StartingLba++; + NumOfLba--; + } + + } while (1); + + VA_END (args); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + + Routine Description: + + Writes data beginning at Lba:Offset from FV. The write terminates eith= er + when *NumBytes of data have been written, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write operation does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + + Arguments: + This - Calling context + Lba - Block in which to begin write + Offset - Offset in the block at which to begin write + NumBytes - On input, indicates the requested write size. = On + output, indicates the actual number of bytes + written + Buffer - Buffer containing source data for the write. + + Returns: + EFI_SUCCESS - The firmware volume was written successfully + EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On outp= ut, + NumBytes contains the total number of bytes + actually written + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled st= ate + EFI_DEVICE_ERROR - The block device is not functioning correctly = and + could not be written + EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL + +--*/ +{ + return QemuFlashWrite ( + (EFI_LBA)Lba, + (UINTN)Offset, + NumBytes, + (UINT8 *)Buffer + ); +} + +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + IN CONST UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + + Routine Description: + + Reads data beginning at Lba:Offset from FV. The Read terminates either + when *NumBytes of data have been read, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write operation does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + + Arguments: + This - Calling context + Lba - Block in which to begin Read + Offset - Offset in the block at which to begin Read + NumBytes - On input, indicates the requested write size. = On + output, indicates the actual number of bytes R= ead + Buffer - Buffer containing source data for the Read. + + Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On outpu= t, + NumBytes contains the total number of bytes + returned in Buffer + EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled sta= te + EFI_DEVICE_ERROR - The block device is not functioning correctly = and + could not be read + EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL + +--*/ +{ + return QemuFlashRead ( + (EFI_LBA)Lba, + (UINTN)Offset, + NumBytes, + (UINT8 *)Buffer + ); +} + +EFI_STATUS +ValidateFvHeader ( + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +/*++ + + Routine Description: + Check the integrity of firmware volume header + + Arguments: + FwVolHeader - A pointer to a firmware volume header + + Returns: + EFI_SUCCESS - The firmware volume is consistent + EFI_NOT_FOUND - The firmware volume has corrupted. So it is no= t an + FV + +--*/ +{ + UINT16 Checksum; + + // + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number + // + if ((FwVolHeader->Revision !=3D EFI_FVH_REVISION) || + (FwVolHeader->Signature !=3D EFI_FVH_SIGNATURE) || + (FwVolHeader->FvLength =3D=3D ((UINTN)-1)) || + ((FwVolHeader->HeaderLength & 0x01) !=3D 0) + ) + { + return EFI_NOT_FOUND; + } + + // + // Verify the header checksum + // + + Checksum =3D CalculateSum16 ( + (UINT16 *)FwVolHeader, + FwVolHeader->HeaderLength + ); + if (Checksum !=3D 0) { + UINT16 Expected; + + Expected =3D + (UINT16)(((UINTN)FwVolHeader->Checksum + 0x10000 - Checksum) & 0xfff= f); + + DEBUG (( + DEBUG_INFO, + "FV@%p Checksum is 0x%x, expected 0x%x\n", + FwVolHeader, + FwVolHeader->Checksum, + Expected + )); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +MarkMemoryRangeForRuntimeAccess ( + EFI_PHYSICAL_ADDRESS BaseAddress, + UINTN Length + ) +{ + EFI_STATUS Status; + + // + // Mark flash region as runtime memory + // + Status =3D gDS->RemoveMemorySpace ( + BaseAddress, + Length + ); + + Status =3D gDS->AddMemorySpace ( + EfiGcdMemoryTypeSystemMemory, + BaseAddress, + Length, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->AllocatePages ( + AllocateAddress, + EfiRuntimeServicesData, + EFI_SIZE_TO_PAGES (Length), + &BaseAddress + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +STATIC +EFI_STATUS +InitializeVariableFvHeader ( + VOID + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *GoodFwVolHeader; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINTN Length; + UINTN WriteLength; + UINTN BlockSize; + + FwVolHeader =3D + (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN) + PcdGet64 (PcdOvmfFlashNvStorageVariableBase); + + Length =3D FixedPcdGet32 (PcdAllVarSize); + BlockSize =3D PcdGet32 (PcdFlashBlockSize); + + Status =3D ValidateFvHeader (FwVolHeader); + if (!EFI_ERROR (Status)) { + if ((FwVolHeader->FvLength !=3D Length) || + (FwVolHeader->BlockMap[0].Length !=3D BlockSize)) + { + Status =3D EFI_VOLUME_CORRUPTED; + } + } + if (EFI_ERROR (Status)) { + UINTN Offset; + UINTN Start; + + DEBUG (( + DEBUG_INFO, + "Variable FV header is not valid. It will be reinitialized.\n" + )); + + // + // Get FvbInfo to provide in FwhInstance. + // + Status =3D GetFvbInfo (Length, &GoodFwVolHeader); + ASSERT (!EFI_ERROR (Status)); + + Start =3D (UINTN)(UINT8*) FwVolHeader - PcdGet64 (PcdFlashFdBase); + ASSERT (Start % BlockSize =3D=3D 0 && Length % BlockSize =3D=3D 0); + ASSERT (GoodFwVolHeader->HeaderLength <=3D BlockSize); + + // + // Erase all the blocks + // + for (Offset =3D Start; Offset < Start + Length; Offset +=3D BlockSize)= { + Status =3D QemuFlashEraseBlock (Offset / BlockSize); + ASSERT_EFI_ERROR (Status); + } + + // + // Write good FV header + // + WriteLength =3D GoodFwVolHeader->HeaderLength; + Status =3D QemuFlashWrite ( + Start / BlockSize, + 0, + &WriteLength, + (UINT8 *)GoodFwVolHeader + ); + ASSERT_EFI_ERROR (Status); + ASSERT (WriteLength =3D=3D GoodFwVolHeader->HeaderLength); + } + + return Status; +} + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + + Routine Description: + This function does common initialization for FVB services + + Arguments: + + Returns: + +--*/ +{ + EFI_STATUS Status; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINT32 BufferSize; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + UINT32 MaxLbaSize; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINTN Length; + UINTN NumOfBlocks; + RETURN_STATUS PcdStatus; + + if (EFI_ERROR (QemuFlashInitialize ())) { + // + // Return an error so image will be unloaded + // + DEBUG (( + DEBUG_INFO, + "QEMU flash was not detected. Writable FVB is not being installed.\n" + )); + return EFI_WRITE_PROTECTED; + } + + // + // Allocate runtime services data for global variable, which contains + // the private data of all firmware volume block instances + // + mFvbModuleGlobal =3D AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL)); + ASSERT (mFvbModuleGlobal !=3D NULL); + + BaseAddress =3D (UINTN) PcdGet64 (PcdOvmfFlashNvStorageVariableBase); + Length =3D PcdGet32 (PcdAllVarSize); + + Status =3D InitializeVariableFvHeader (); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_INFO, + "QEMU Flash: Unable to initialize variable FV header\n" + )); + return EFI_WRITE_PROTECTED; + } + + FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress; + Status =3D ValidateFvHeader (FwVolHeader); + if (EFI_ERROR (Status)) { + // + // Get FvbInfo + // + Status =3D GetFvbInfo (Length, &FwVolHeader); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "EFI_ERROR (GetFvbInfo (Length, &FwVolHeader))\n= ")); + return EFI_WRITE_PROTECTED; + } + } + + BufferSize =3D (sizeof (EFI_FW_VOL_INSTANCE) + + FwVolHeader->HeaderLength - + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + ); + mFvbModuleGlobal->FvInstance =3D AllocateRuntimePool (BufferSize); + ASSERT (mFvbModuleGlobal->FvInstance !=3D NULL); + + FwhInstance =3D mFvbModuleGlobal->FvInstance; + + mFvbModuleGlobal->NumFv =3D 0; + MaxLbaSize =3D 0; + + FwVolHeader =3D + (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN) + PcdGet64 (PcdOvmfFlashNvStorageVariableBase); + + FwhInstance->FvBase =3D (UINTN)BaseAddress; + + CopyMem ( + (UINTN *)&(FwhInstance->VolumeHeader), + (UINTN *)FwVolHeader, + FwVolHeader->HeaderLength + ); + FwVolHeader =3D &(FwhInstance->VolumeHeader); + + NumOfBlocks =3D 0; + + for (PtrBlockMapEntry =3D FwVolHeader->BlockMap; + PtrBlockMapEntry->NumBlocks !=3D 0; + PtrBlockMapEntry++) + { + // + // Get the maximum size of a block. + // + if (MaxLbaSize < PtrBlockMapEntry->Length) { + MaxLbaSize =3D PtrBlockMapEntry->Length; + } + + NumOfBlocks =3D NumOfBlocks + PtrBlockMapEntry->NumBlocks; + } + + // + // The total number of blocks in the FV. + // + FwhInstance->NumOfBlocks =3D NumOfBlocks; + + // + // Add a FVB Protocol Instance + // + FvbDevice =3D AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE)); + ASSERT (FvbDevice !=3D NULL); + + CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE= )); + + FvbDevice->Instance =3D mFvbModuleGlobal->NumFv; + mFvbModuleGlobal->NumFv++; + + // + // Set up the devicepath + // + if (FwVolHeader->ExtHeaderOffset =3D=3D 0) { + FV_MEMMAP_DEVICE_PATH *FvMemmapDevicePath; + + // + // FV does not contains extension header, then produce MEMMAP_DEVICE_P= ATH + // + FvMemmapDevicePath =3D AllocateCopyPool ( + sizeof (FV_MEMMAP_DEVICE_PATH), + &mFvMemmapDevicePathTemplate + ); + FvMemmapDevicePath->MemMapDevPath.StartingAddress =3D BaseAddress; + FvMemmapDevicePath->MemMapDevPath.EndingAddress =3D + BaseAddress + FwVolHeader->FvLength - 1; + FvbDevice->DevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *)FvMemmapDevicePa= th; + } else { + FV_PIWG_DEVICE_PATH *FvPiwgDevicePath; + + FvPiwgDevicePath =3D AllocateCopyPool ( + sizeof (FV_PIWG_DEVICE_PATH), + &mFvPIWGDevicePathTemplate + ); + CopyGuid ( + &FvPiwgDevicePath->FvDevPath.FvName, + (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset) + ); + FvbDevice->DevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *)FvPiwgDevicePath; + } + + // + // Module type specific hook. + // + InstallProtocolInterfaces (FvbDevice); + + MarkMemoryRangeForRuntimeAccess (BaseAddress, Length); + + // + // Set several PCD values to point to flash + // + + + PcdStatus =3D PcdSet64S ( + PcdFlashNvStorageVariableBase64, + (UINTN) PcdGet64 (PcdOvmfFlashNvStorageVariableBase) + ); + ASSERT_RETURN_ERROR (PcdStatus); + PcdStatus =3D PcdSet64S ( + PcdFlashNvStorageFtwWorkingBase64, + PcdGet64 (PcdOvmfFlashNvStorageFtwWorkingBase) + ); + ASSERT_RETURN_ERROR (PcdStatus); + PcdStatus =3D PcdSet64S ( + PcdFlashNvStorageFtwSpareBase64, + PcdGet64 (PcdOvmfFlashNvStorageFtwSpareBase) + ); + ASSERT_RETURN_ERROR (PcdStatus); + + FwhInstance =3D (EFI_FW_VOL_INSTANCE *) + ( + (UINTN)((UINT8 *)FwhInstance) + FwVolHeader->HeaderLength= + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLU= ME_HEADER)) + ); + + // + // Module type specific hook. + // + InstallVirtualAddressChangeHandler (); + + PcdStatus =3D PcdSetBoolS (PcdOvmfFlashVariablesEnable, TRUE); + ASSERT_RETURN_ERROR (PcdStatus); + return EFI_SUCCESS; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbService= sRuntimeDxe/FwBlockService.h b/Platform/Loongson/LoongArchQemuPkg/Drivers/Q= emuFlashFvbServicesRuntimeDxe/FwBlockService.h new file mode 100644 index 0000000000..e7234a0c5e --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntim= eDxe/FwBlockService.h @@ -0,0 +1,178 @@ +/** @file + Firmware volume block driver for Intel Firmware Hub (FWH) device + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef _FW_BLOCK_SERVICE_H +#define _FW_BLOCK_SERVICE_H + +typedef struct { + UINTN FvBase; + UINTN NumOfBlocks; + EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; +} EFI_FW_VOL_INSTANCE; + +typedef struct { + UINT32 NumFv; + EFI_FW_VOL_INSTANCE *FvInstance; +} ESAL_FWB_GLOBAL; + +extern ESAL_FWB_GLOBAL *mFvbModuleGlobal; + +// +// Fvb Protocol instance data +// +#define FVB_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE,\ + FwVolBlockInstance, FVB_DEVICE_SIGNATURE) + +#define FVB_EXTEND_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE,\ + FvbExtension, FVB_DEVICE_SIGNATUR= E) + +#define FVB_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'V', 'B', 'N') + +typedef struct { + MEDIA_FW_VOL_DEVICE_PATH FvDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_PIWG_DEVICE_PATH; + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_MEMMAP_DEVICE_PATH; + +typedef struct { + UINTN Signature; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN Instance; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance; +} EFI_FW_VOL_BLOCK_DEVICE; + +EFI_STATUS +GetFvbInfo ( + IN UINT64 FvLength, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ); + +EFI_STATUS +FvbSetVolumeAttributes ( + IN UINTN Instance, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes, + IN ESAL_FWB_GLOBAL *Global + ); + +EFI_STATUS +FvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes, + IN ESAL_FWB_GLOBAL *Global + ); + +EFI_STATUS +FvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *Address, + IN ESAL_FWB_GLOBAL *Global + ); + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +VOID +EFIAPI +FvbClassAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +EFI_STATUS +FvbGetLbaAddress ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks, + IN ESAL_FWB_GLOBAL *Global + ); + +// +// Protocol APIs +// +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ); + +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ); + +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + IN CONST UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ); + +// +// The following functions have different implementations dependent on the +// module type chosen for building this driver. +// +VOID +InstallProtocolInterfaces ( + IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice + ); + +VOID +InstallVirtualAddressChangeHandler ( + VOID + ); +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbService= sRuntimeDxe/FwBlockServiceDxe.c b/Platform/Loongson/LoongArchQemuPkg/Driver= s/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c new file mode 100644 index 0000000000..cb85499539 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntim= eDxe/FwBlockServiceDxe.c @@ -0,0 +1,152 @@ +/** @file + Functions related to the Firmware Volume Block service whose + implementation is specific to the runtime DXE driver build. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FwBlockService.h" +#include "QemuFlash.h" + +VOID +InstallProtocolInterfaces ( + IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice + ) +{ + EFI_STATUS Status; + EFI_HANDLE FwbHandle; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; + + // + // Find a handle with a matching device path that has supports FW Block + // protocol + // + Status =3D gBS->LocateDevicePath ( + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->DevicePath, + &FwbHandle + ); + if (EFI_ERROR (Status)) { + // + // LocateDevicePath fails so install a new interface and device path + // + FwbHandle =3D NULL; + DEBUG ((DEBUG_INFO, "Installing QEMU flash FVB\n")); + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->FwVolBlockInstance, + &gEfiDevicePathProtocolGuid, + FvbDevice->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else if (IsDevicePathEnd (FvbDevice->DevicePath)) { + // + // Device already exists, so reinstall the FVB protocol + // + Status =3D gBS->HandleProtocol ( + FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **)&OldFwbInterface + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "Reinstalling FVB for QEMU flash region\n")); + Status =3D gBS->ReinstallProtocolInterface ( + FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + OldFwbInterface, + &FvbDevice->FwVolBlockInstance + ); + ASSERT_EFI_ERROR (Status); + } else { + // + // There was a FVB protocol on an End Device Path node + // + ASSERT (FALSE); + } +} + + +STATIC +VOID +EFIAPI +FvbVirtualAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + + Routine Description: + + Fixup internal data so that EFI and SAL can be call in virtual mode. + Call the passed in Child Notify event and convert the mFvbModuleGlobal + date items to there virtual address. + + Arguments: + + (Standard EFI notify event - EFI_EVENT_NOTIFY) + + Returns: + + None + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN Index; + + FwhInstance =3D mFvbModuleGlobal->FvInstance; + EfiConvertPointer (0x0, (VOID **)&mFvbModuleGlobal->FvInstance); + + // + // Convert the base address of all the instances + // + Index =3D 0; + while (Index < mFvbModuleGlobal->NumFv) { + EfiConvertPointer (0x0, (VOID **)&FwhInstance->FvBase); + FwhInstance =3D (EFI_FW_VOL_INSTANCE *) + ( + (UINTN)((UINT8 *)FwhInstance) + + FwhInstance->VolumeHeader.HeaderLength + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VO= LUME_HEADER)) + ); + Index++; + } + + EfiConvertPointer (0x0, (VOID **)&mFvbModuleGlobal); + QemuFlashConvertPointers (); +} + + +VOID +InstallVirtualAddressChangeHandler ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT VirtualAddressChangeEvent; + + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + FvbVirtualAddressChangeEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &VirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbService= sRuntimeDxe/QemuFlash.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFl= ashFvbServicesRuntimeDxe/QemuFlash.c new file mode 100644 index 0000000000..a85d736060 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntim= eDxe/QemuFlash.c @@ -0,0 +1,251 @@ +/** @file + LoongArch support for QEMU system firmware flash device + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include "QemuFlash.h" + +#define WRITE_BYTE_CMD 0x10 +#define BLOCK_ERASE_CMD 0x20 +#define CLEAR_STATUS_CMD 0x50 +#define READ_STATUS_CMD 0x70 +#define READ_DEVID_CMD 0x90 +#define BLOCK_ERASE_CONFIRM_CMD 0xd0 +#define READ_ARRAY_CMD 0xff + +#define CLEARED_ARRAY_STATUS 0x00 + +UINT8 *mFlashBase; + +STATIC UINTN mFdBlockSize =3D 0; +STATIC UINTN mFdBlockCount =3D 0; + +STATIC +volatile UINT8 * +QemuFlashPtr ( + IN EFI_LBA Lba, + IN UINTN Offset + ) +{ + return mFlashBase + ((UINTN)Lba * mFdBlockSize) + Offset; +} + + +/** + Determines if the QEMU flash memory device is present. + + @retval FALSE The QEMU flash device is not present. + @retval TRUE The QEMU flash device is present. + +**/ +STATIC +BOOLEAN +QemuFlashDetected ( + VOID + ) +{ + BOOLEAN FlashDetected; + volatile UINT8 *Ptr; + + UINTN Offset; + UINT8 OriginalUint8; + UINT8 ProbeUint8; + + FlashDetected =3D FALSE; + Ptr =3D QemuFlashPtr (0, 0); + + for (Offset =3D 0; Offset < mFdBlockSize; Offset++) { + Ptr =3D QemuFlashPtr (0, Offset); + ProbeUint8 =3D *Ptr; + if ((ProbeUint8 !=3D CLEAR_STATUS_CMD) && + (ProbeUint8 !=3D READ_STATUS_CMD) && + (ProbeUint8 !=3D CLEARED_ARRAY_STATUS)) + { + break; + } + } + + if (Offset >=3D mFdBlockSize) { + DEBUG ((DEBUG_INFO, "QEMU Flash: Failed to find probe location\n")); + return FALSE; + } + + DEBUG ((DEBUG_INFO, "QEMU Flash: Attempting flash detection at %p\n", Pt= r)); + + OriginalUint8 =3D *Ptr; + *Ptr =3D CLEAR_STATUS_CMD; + ProbeUint8 =3D *Ptr; + if ((OriginalUint8 !=3D CLEAR_STATUS_CMD) && + (ProbeUint8 =3D=3D CLEAR_STATUS_CMD)) + { + DEBUG ((DEBUG_INFO, "QemuFlashDetected =3D> FD behaves as RAM\n")); + *Ptr =3D OriginalUint8; + } else { + *Ptr =3D READ_STATUS_CMD; + ProbeUint8 =3D *Ptr; + if (ProbeUint8 =3D=3D OriginalUint8) { + DEBUG ((DEBUG_INFO, "QemuFlashDetected =3D> FD behaves as ROM\n")); + } else if (ProbeUint8 =3D=3D READ_STATUS_CMD) { + DEBUG ((DEBUG_INFO, "QemuFlashDetected =3D> FD behaves as RAM\n")); + *Ptr =3D OriginalUint8; + } else if (ProbeUint8 =3D=3D CLEARED_ARRAY_STATUS) { + DEBUG ((DEBUG_INFO, "QemuFlashDetected =3D> FD behaves as FLASH\n")); + FlashDetected =3D TRUE; + *Ptr =3D READ_ARRAY_CMD; + } + } + + DEBUG (( + DEBUG_INFO, + "QemuFlashDetected =3D> %a\n", + FlashDetected ? "Yes" : "No" + )); + return FlashDetected; +} + + +/** + Read from QEMU Flash + + @param[in] Lba The starting logical block index to read from. + @param[in] Offset Offset into the block at which to begin reading. + @param[in] NumBytes On input, indicates the requested read size. On + output, indicates the actual number of bytes read + @param[in] Buffer Pointer to the buffer to read into. + +**/ +EFI_STATUS +QemuFlashRead ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + UINT8 *Ptr; + + // + // Only write to the first 64k. We don't bother saving the FTW Spare + // block into the flash memory. + // + if (Lba >=3D mFdBlockCount) { + return EFI_INVALID_PARAMETER; + } + + // + // Get flash address + // + Ptr =3D (UINT8 *)QemuFlashPtr (Lba, Offset); + + CopyMem (Buffer, Ptr, *NumBytes); + + return EFI_SUCCESS; +} + + +/** + Write to QEMU Flash + + @param[in] Lba The starting logical block index to write to. + @param[in] Offset Offset into the block at which to begin writing. + @param[in] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Pointer to the data to write. + +**/ +EFI_STATUS +QemuFlashWrite ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + volatile UINT8 *Ptr; + UINTN Loop; + + // + // Only write to the first 64k. We don't bother saving the FTW Spare + // block into the flash memory. + // + if (Lba >=3D mFdBlockCount) { + return EFI_INVALID_PARAMETER; + } + + // + // Program flash + // + Ptr =3D QemuFlashPtr (Lba, Offset); + for (Loop =3D 0; Loop < *NumBytes; Loop++) { + *Ptr =3D WRITE_BYTE_CMD; + *Ptr =3D Buffer[Loop]; + Ptr++; + } + + // + // Restore flash to read mode + // + if (*NumBytes > 0) { + *(Ptr - 1) =3D READ_ARRAY_CMD; + } + + return EFI_SUCCESS; +} + + +/** + Erase a QEMU Flash block + + @param Lba The logical block index to erase. + +**/ +EFI_STATUS +QemuFlashEraseBlock ( + IN EFI_LBA Lba + ) +{ + volatile UINT8 *Ptr; + + if (Lba >=3D mFdBlockCount) { + return EFI_INVALID_PARAMETER; + } + + Ptr =3D QemuFlashPtr (Lba, 0); + *Ptr =3D BLOCK_ERASE_CMD; + *Ptr =3D BLOCK_ERASE_CONFIRM_CMD; + return EFI_SUCCESS; +} + + +/** + Initializes QEMU flash memory support + + @retval EFI_WRITE_PROTECTED The QEMU flash device is not present. + @retval EFI_SUCCESS The QEMU flash device is supported. + +**/ +EFI_STATUS +QemuFlashInitialize ( + VOID + ) +{ + mFlashBase =3D (UINT8 *)(UINTN)PcdGet64 (PcdOvmfFlashNvStorageVariable= Base); + mFdBlockSize =3D PcdGet32 (PcdFlashBlockSize); + ASSERT(PcdGet32 (PcdAllVarSize) % mFdBlockSize =3D=3D 0); + mFdBlockCount =3D PcdGet32 (PcdAllVarSize) / mFdBlockSize; + + if (!QemuFlashDetected ()) { + return EFI_WRITE_PROTECTED; + } + + return EFI_SUCCESS; +} + diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbService= sRuntimeDxe/QemuFlash.h b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFl= ashFvbServicesRuntimeDxe/QemuFlash.h new file mode 100644 index 0000000000..27caabc5f0 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntim= eDxe/QemuFlash.h @@ -0,0 +1,86 @@ +/** @file + LoongArch support for QEMU system firmware flash device + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __QEMU_FLASH_H__ +#define __QEMU_FLASH_H__ + +#include + +extern UINT8 *mFlashBase; + +/** + Read from QEMU Flash + + @param[in] Lba The starting logical block index to read from. + @param[in] Offset Offset into the block at which to begin reading. + @param[in] NumBytes On input, indicates the requested read size. On + output, indicates the actual number of bytes read + @param[in] Buffer Pointer to the buffer to read into. + +**/ +EFI_STATUS +QemuFlashRead ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ); + + +/** + Write to QEMU Flash + + @param[in] Lba The starting logical block index to write to. + @param[in] Offset Offset into the block at which to begin writing. + @param[in] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Pointer to the data to write. + +**/ +EFI_STATUS +QemuFlashWrite ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ); + + +/** + Erase a QEMU Flash block + + @param Lba The logical block index to erase. + +**/ +EFI_STATUS +QemuFlashEraseBlock ( + IN EFI_LBA Lba + ); + + +/** + Initializes QEMU flash memory support + + @retval EFI_WRITE_PROTECTED The QEMU flash device is not present. + @retval EFI_SUCCESS The QEMU flash device is supported. + +**/ +EFI_STATUS +QemuFlashInitialize ( + VOID + ); + + +VOID +QemuFlashConvertPointers ( + VOID + ); + +#endif + diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbService= sRuntimeDxe/QemuFlashDxe.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/Qem= uFlashFvbServicesRuntimeDxe/QemuFlashDxe.c new file mode 100644 index 0000000000..b63314aac2 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntim= eDxe/QemuFlashDxe.c @@ -0,0 +1,21 @@ +/** @file + LoongArch support for QEMU system firmware flash device: functions speci= fic to the + runtime DXE driver build. + + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include "QemuFlash.h" + +VOID +QemuFlashConvertPointers ( + VOID + ) +{ + EfiConvertPointer (0x0, (VOID **)&mFlashBase); +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.dsc index 578b80b7b0..ed06558f18 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc @@ -171,10 +171,10 @@ VirtioLib | OvmfPkg/Library/VirtioLib/VirtioLib.i= nf FrameBufferBltLib | MdeModulePkg/Library/FrameBufferBltLi= b/FrameBufferBltLib.inf QemuFwCfgLib | OvmfPkg/Library/QemuFwCfgLib/QemuFwCf= gLibMmio.inf - DebugLib | MdePkg/Library/BaseDebugLibSerialPort= /BaseDebugLibSerialPort.inf - PeiServicesLib | MdePkg/Library/PeiServicesLib/PeiServ= icesLib.inf + VariableFlashInfoLib | MdeModulePkg/Library/BaseVariableFlas= hInfoLib/BaseVariableFlashInfoLib.inf + [LibraryClasses.common.SEC] ReportStatusCodeLib | MdeModulePkg/Library/PeiReportStatusC= odeLib/PeiReportStatusCodeLib.inf HobLib | MdePkg/Library/PeiHobLib/PeiHobLib.inf --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93896): https://edk2.groups.io/g/devel/message/93896 Mute This Topic: https://groups.io/mt/93715815/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 26 21:30:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+93900+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93900+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1663299415; cv=none; d=zohomail.com; s=zohoarc; b=CTO4xn2nUDy8eVSg4DY93rn2IwGPIcLBkTwYayMJhqPSo2P4tu5SW0ZOTI9Sva6JZoMJYVSLYMwoBSTsc+vYRkSAgqZgSTddGZlGW+z9fsjt6tLXmatBXQMVpFtD3YzK3PgXyW8n5gA1iwWo77V8ogchIj0Vfaxj7KG4bZCQmLo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663299415; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=ef0Ht2ZDh94MRKnKei/6qluqfdouZQxE4El80sy+R1E=; b=Fytk2gZGOCUhw2YNr1Ts3pAtCwo90gos0sM9v/So0ij3/Ri0L5haseFhgFzKJXpBJWp8psLn3GBK8eJWP1Xz9bhsMLN3+4WlpCVumtgaP6EQYk19e81hga/z3LoCr2W3Kr5PaBzGYW/sMYfET8wybxwUiwdQ0HqHDBnZrJumeoQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+93900+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663299415309116.4194981352772; Thu, 15 Sep 2022 20:36:55 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id fZmhYY1788612xLZgRmNL2Gj; Thu, 15 Sep 2022 20:36:55 -0700 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web10.2142.1663299408350296321 for ; Thu, 15 Sep 2022 20:36:54 -0700 X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S18; Fri, 16 Sep 2022 11:36:46 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-devel] [edk2-platforms][PATCH V2 16/16] Platform/Loongson: Support for saving variables to flash. Date: Fri, 16 Sep 2022 11:36:33 +0800 Message-Id: <47b484e939b323a294973f7f29b9b01523b4db2b.1663298005.git.lixianglai@loongson.cn> In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S18 X-Coremail-Antispam: 1UD129KBjvJXoWxtrWUJry3CryUJryfuF4xCrg_yoW3Aw48pr 4UuFn7Kr1kKr4Utr1Yy34DWwnxAryak3s8Jw43tr17WF9rJ3WDG3yjva15Ary7A347tryx tr409w4UuF1qv3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: QwEmDBra3XMSTuKyWdT0C6zYx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663299415; bh=4lSTme48rqk0ss2i/QRBJiY86+NmrJQrU6F08xX89ic=; h=Cc:Date:From:Reply-To:Subject:To; b=ZXe+ex752hHhvgnMd8SZF4pVNKJMj8ZNjS/9UrclmASGL/cgbVPiq2mxFZmZHPO/fis OjZYv3L45dzhRCTL7+YetCLJjuv0Px7yltQer/u0A5HlLqJZ0gjQGGgezgJU0pZQ7dNsv RMQZqujFmhewt/Px2R2p3B0UWT0KbUEngMs= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663299416321100053 Content-Type: text/plain; charset="utf-8" Added the function of saving non-volatile variables. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- Platform/Loongson/LoongArchQemuPkg/Loongson.dec | 6 ++++++ Platform/Loongson/LoongArchQemuPkg/Loongson.dsc | 2 +- Platform/Loongson/LoongArchQemuPkg/Loongson.fdf | 14 ++++++++++++++ .../Loongson/LoongArchQemuPkg/Loongson.fdf.inc | 11 +++++++++++ .../Loongson/LoongArchQemuPkg/VarStore.fdf.inc | 10 +++++----- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.dec index 508a770a22..c3e523b39b 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec @@ -32,6 +32,8 @@ [Protocols] =20 [PcdsFixedAtBuild, PcdsDynamic] + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashFdBase|0x0|UINT64|0 + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashBlockSize|0x0|UINT32|2 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase|0x0|UINT64|0x00000003 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize|0x0|UINT32|0x00000004 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvOffset|0x0|UINT64|0x00000007 @@ -50,6 +52,10 @@ gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize|0|UINT32|0x0000001d gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop|0x0|UINT64|0x0000001e gLoongArchQemuPkgTokenSpaceGuid.PcdRamRegionsBottom|0x0|UINT64|0x00000022 + gLoongArchQemuPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase|0x0|UI= NT64|0x00000024 + gLoongArchQemuPkgTokenSpaceGuid.PcdAllVarSize|0x0|UINT32|0x00000025 + gLoongArchQemuPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase|0x0|UI= NT64|0x00000026 + gLoongArchQemuPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase|0x0|= UINT64|0x00000027 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase|0x0|UINT64|0x00000028 gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize|0x0|UINT32|0x00000029 =20 diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.dsc index ed06558f18..ec6234a26e 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc @@ -447,7 +447,7 @@ # # Variable # -# Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntimeD= xe/FvbServicesRuntimeDxe.inf + Platform/Loongson/LoongArchQemuPkg/Drivers/QemuFlashFvbServicesRuntimeDx= e/FvbServicesRuntimeDxe.inf OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf { PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.i= nf diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf b/Platform/Loo= ngson/LoongArchQemuPkg/Loongson.fdf index ba2942e455..12920a0833 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf @@ -31,6 +31,19 @@ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvBase|gLoong= ArchQemuPkgTokenSpaceGui FV =3D FVMAIN_COMPACT =20 !include VarStore.fdf.inc + +##########################################################################= ########################### +[FD.QEMU_EFI_VARS] +BaseAddress =3D $(VARIABLE_BASE_ADDRESS) +Size =3D $(VAR_ALL_SIZE) +ErasePolarity =3D 1 +BlockSize =3D $(BLOCK_SIZE) +NumBlocks =3D $(VAR_ALL_BLOCKS) + +DEFINE VARIABLE_OFFSET =3D 0 +!include VarStore.fdf.inc +DEFINE VARIABLE_OFFSET =3D 0x003a0000 + ##########################################################################= ########################### [FV.SECFV] FvNameGuid =3D 587d4265-5e71-41da-9c35-4258551f1e22 @@ -87,6 +100,7 @@ INF MdeModulePkg/Core/Pei/PeiMain.inf INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf INF Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf + ##########################################################################= ########################### [FV.DXEFV] FvNameGuid =3D 5d19a5b3-130f-459b-a292-9270a9e6bc62 diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc b/Platform= /Loongson/LoongArchQemuPkg/Loongson.fdf.inc index 964d69ed44..4b926a85ff 100644 --- a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc @@ -34,6 +34,7 @@ DEFINE VAR_ALL_SIZE =3D 0x60000 =20 ##########################################################################= ## #Set Var Flash layout +DEFINE VARIABLE_BASE_ADDRESS =3D 0x1c3a0000 DEFINE VARIABLE_SIZE =3D 0x00010000 DEFINE VAR_ALL_BLOCKS =3D 0x60 =20 @@ -53,11 +54,21 @@ DEFINE EVENT_LOG_OFFSET =3D $(FWTWORKING_OFFS= ET) + $(FWTWORKING_SIZE) DEFINE EVENT_LOG_SIZE =3D 0x8000 =20 # Set Variable +SET gLoongArchQemuPkgTokenSpaceGuid.PcdFlashFdBase =3D $(FD_BASE_ADDRESS) + +SET gLoongArchQemuPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase =3D = $(FD_BASE_ADDRESS) + $(VARIABLE_OFFSET) +SET gLoongArchQemuPkgTokenSpaceGuid.PcdAllVarSize =3D $(VAR_ALL_SIZE) + +SET gLoongArchQemuPkgTokenSpaceGuid.PcdFlashBlockSize =3D $(BLOCK_SIZE) SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 =3D 0 SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize =3D $(VAR= IABLE_SIZE) =20 # Set FtwSpare +SET gLoongArchQemuPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase =3D= $(FD_BASE_ADDRESS) + $(SPARE_OFFSET) +SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 =3D 0 SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize =3D $(SPA= RE_SIZE) =20 # Set FtwWorking +SET gLoongArchQemuPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase = =3D $(FD_BASE_ADDRESS) + $(SPARE_OFFSET) + $(SPARE_SIZE) +SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 =3D 0 SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize =3D $(F= WTWORKING_SIZE) diff --git a/Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc b/Platform= /Loongson/LoongArchQemuPkg/VarStore.fdf.inc index 625fa23543..a4e0158cf8 100644 --- a/Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc +++ b/Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc @@ -38,16 +38,16 @@ DATA =3D { # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32 0x5a, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -$(RESERVE1_OFFSET)|$(RESERVE1_SIZE) +$(VARIABLE_OFFSET) + $(VARIABLE_SIZE)|$(RESERVE1_SIZE) #NV_RESERVE1_STORE =20 -$(RESERVE2_OFFSET)|$(RESERVE2_SIZE) +$(VARIABLE_OFFSET) + $(VARIABLE_SIZE) + $(RESERVE1_SIZE)|$(RESERVE2_SIZE) #NV_RESERVE2_STORE =20 -$(SPARE_OFFSET)|$(SPARE_SIZE) +$(VARIABLE_OFFSET) + $(VARIABLE_SIZE) + $(RESERVE1_SIZE) + $(RESERVE2_SIZE= )|$(SPARE_SIZE) #NV_FTW_SPARE =20 -$(FWTWORKING_OFFSET)|$(FWTWORKING_SIZE) +$(VARIABLE_OFFSET) + $(VARIABLE_SIZE) + $(RESERVE1_SIZE) + $(RESERVE2_SIZE= ) + $(SPARE_SIZE)|$(FWTWORKING_SIZE) #NV_FTW_WORKING DATA =3D { # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature =3D gEdkiiWorkingBl= ockSignatureGuid =3D @@ -60,5 +60,5 @@ DATA =3D { 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } =20 -$(EVENT_LOG_OFFSET)|$(EVENT_LOG_SIZE) +$(VARIABLE_OFFSET) + $(VARIABLE_SIZE) + $(RESERVE1_SIZE) + $(RESERVE2_SIZE= ) + $(SPARE_SIZE) + $(FWTWORKING_SIZE)|$(EVENT_LOG_SIZE) #NV_EVENT_LOG --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#93900): https://edk2.groups.io/g/devel/message/93900 Mute This Topic: https://groups.io/mt/93715819/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-