Adb命令
2025-06-04
#禁用应用
adb shell pm disable-user --user 0 com.vivo.browser
#列出已经禁用的应用
adb shell pm list packages -d
#启用应用
adb shell pm enable com.vivo.browser
#禁用应用
adb shell pm disable-user --user 0 com.vivo.browser
#列出已经禁用的应用
adb shell pm list packages -d
#启用应用
adb shell pm enable com.vivo.browser
CONFIG_ACPI_DEBUGGER=y
这个参数,否则是无法打印的,不过ubuntu在Ubuntu 18.04 (x64)之后就默认设置了这个参数,所以可以我们可以使用ubuntu系统来做AML的调试。下面所有的代码调试都是在ubuntu server 22.04.5上实现。99_config.yaml
,填充如下内容(详细可参考
Configuring networks|Ubuntu)network:
version: 2
renderer: networkd
ethernets:
enp0s8:
#IP配置取决于当前virtualbox总配置的IP地址
addresses:
- "192.168.168.168/24"
enp0s3:
#virtualbox nat,下面这些信息直接填照抄即可。
addresses:
- "10.0.2.15/24"
nameservers:
addresses: [8.8.8.8]
routes:
- to: default
via: 10.0.2.2
netplan apply
让网络配置生效,此时就可以通过ssh连接到虚拟机内部了。/var/cache/apt/archives
目录下,将该目录下的deb包打包传递到服务器上安装即可。apt install linux-tools-`uname -r` linux-tools-generic --download-only
Method (_SUN, 0, NotSerialized) // _SUN: Slot User Number
{
Printf("VendorId = %o, DeviceId = %o, Slot = %o", VEND, DEVI, SLTN)
Return (SLTN)
}
acpidbg
,就可以进行调试了。acpidbg
常用的命令如namespace
、paths
、execute
。namespace
会打印出ACPI的层级关系,如下图所示root@server:~# acpidbg
- namespace
ACPI Namespace (from Namespace Root):
0 _GPE Scope 0000000008fab98e 000
0 _PR_ Scope 000000005953797b 000
1 C000 Processor 00000000a1ac5d21 01A ID 00 Len 06 Addr 0000000000000810
2 _PCT Package 00000000a7326f94 01B Elements 02
2 _PSS Package 0000000046ef281e 01B Elements 03
2 XPSS Package 000000005f13ae73 01B Elements 03
2 _PSD Package 000000009366b23a 01B Elements 01
2 PPCV Integer 000000009ee3a624 01B = 0000000000000000
2 _PPC Method 000000007965a545 01B Args 0 Len 0005 Aml 00000000be65bdfb
1 C001 Processor 000000005eb2da62 01A ID 01 Len 06 Addr 0000000000000810
2 _PCT Package 00000000ee112324 01B Elements 02
2 _PSS Package 0000000091ffd188 01B Elements 03
2 XPSS Package 00000000fb1c13d0 01B Elements 03
2 _PSD Package 0000000039eb741a 01B Elements 01
2 PPCV Integer 00000000df6eb317 01B = 0000000000000000
2 _PPC Method 000000000665d99d 01B Args 0 Len 0005 Aml 00000000fdc3368c
1 C002 Processor 00000000bfa4f34a 01A ID 02 Len 06 Addr 0000000000000810
paths
会打印出namespace objects的全路径名#从左到右依次是层级、Object类型以及全路径名
3 Device _SB.S0D2.D2C0
4 Integer _SB.S0D2.D2C0._ADR
4 Method _SB.S0D2.D2C0._PRW
4 Method _SB.S0D2.D2C0._PRT
4 Region _SB.S0D2.D2C0.K1PC
4 RegionField _SB.S0D2.D2C0.K1SL
4 Device _SB.S0D2.D2C0.BRG1
5 Integer _SB.S0D2.D2C0.BRG1._ADR
5 Device _SB.S0D2.D2C0.BRG1.BRG2
6 Integer _SB.S0D2.D2C0.BRG1.BRG2._ADR
6 Device _SB.S0D2.D2C0.BRG1.BRG2.BRG3
7 Integer _SB.S0D2.D2C0.BRG1.BRG2.BRG3._ADR
7 Region _SB.S0D2.D2C0.BRG1.BRG2.BRG3.PP8C
7 RegionField _SB.S0D2.D2C0.BRG1.BRG2.BRG3.VEND
7 RegionField _SB.S0D2.D2C0.BRG1.BRG2.BRG3.DEVI
7 Method _SB.S0D2.D2C0.BRG1.BRG2.BRG3._SUN
3 Device _SB.S0D2.D2C1
4 Integer _SB.S0D2.D2C1._ADR
execute
命令。#查看_ADR的值
- execute _SB.S0D2.D2C0._ADR
Evaluating \_SB.S0D2.D2C0._ADR
Evaluation of \_SB.S0D2.D2C0._ADR returned object 000000003e779e35, external buffer length 18
[Integer] = 0000000000030001
#查看_SUN method的执行结果
- execute _SB.S0D2.D2C0.BRG1.BRG2.BRG3._SUN
Evaluating \_SB.S0D2.D2C0.BRG1.BRG2.BRG3._SUN
ACPI Debug: "VendorId = 0000000000001D94, DeviceId = 0000000000006210, Slot = 0000000000000002"
Evaluation of \_SB.S0D2.D2C0.BRG1.BRG2.BRG3._SUN returned object 000000003e779e35, external buffer length 18
[Integer] = 0000000000000002
#查看RegionField的值
- execute _SB.S0D2.D2C0.BRG1.BRG2.BRG3.VEND
Evaluating \_SB.S0D2.D2C0.BRG1.BRG2.BRG3.VEND
Evaluation of \_SB.S0D2.D2C0.BRG1.BRG2.BRG3.VEND returned object 0000000066540b46, external buffer length 18
[Integer] = 0000000000001D94
/etc/default/grub
文件,加入如下配置信息(具体含义可以参考
ACPI Debug Output),并执行update-grub
让其生效,随后重启就能在dmesg中看到ASL中的打印信息了。GRUB_CMDLINE_LINUX_DEFAULT="acpi.debug_layer=0xFFFFFFFF acpi.debug_level=0x2"
包含三种错误检测机制
其中BIOS侧用的比较多的是Error Messages,可以用来向主机报告错误。
EP上的Error Messages会被发送到相应的Root Ports。
Error Message包括ERR_COR(CE)、ERR_NONFATAL(NON-FATAL UCE)、ERR_FATAL(FATAL UCE)
Root Port是一个PCI-PCI Bridge结构,是从PCIe Root Complex出来的PCIe Link。
PCIe配置空间为0~0xFFF,其中0~0xFF为PCI兼容配置空间(PCI-compatible region),0x40~0xFF会存放Capability结构,PCI Express Capability就位于0x40~0xFF的位置。0x100~0xFFF是PCIe扩展配置空间(PCI Express Extended Configuration Space)。PCI兼容配置空间可以通过传统的IO寄存器和ECAM访问,PCIe扩展配置空间只能通过ECAM访问(PCI Express Enhanced Configuration Access Mechanism)
PCI Express Capability的结构如下图所示,所有的PCIe设备都需要支持该Capability,
PCI Express Extended Capability寄存器位于PCI配置空间的0xFF之后,在0x100~0xFFF这段空间。AER寄存器就位于这段空间。
往AER的CE MASK寄存器对应BIT写1,可以屏蔽对应CE上报。
error messages生成的流程
error messages上报流程
NON-FATAL 的错误可能是不需要执行任何的恢复动作的,比如软件尝试从一个不存在的设置执行一个读取操作,Completion中的UR Status将会报告一个错误,此时如果软件为Completer额外产生一个ERR_NONFATAL Message,就可能会导致系统运行异常;Advisory Non-Fatal Error cases可以让在产生NON_FATAL ERROR时发送ERR_COR Message。如果将ERR的严重级别设置为FATAL,ERR将会以ERR_FATAL发出该错误。
开启Linux串口可以收集OS的日志,也可以解决OS下BIOS日志显示不全的问题
开启步骤如下:
vim /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200n8"
GRUB_TERMINAL=serial
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"
grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
GHES:Failed to read error status block!
,后续重新编译Linux内核,才定位到错误。cp /boot/config-4.18.0-193.el8.x86_64 .config
make menuconfig
,之后找找有没有自己感兴趣的配置,把它选上后,保存退出。make -j128
,其中-j表示并行编译,可以加快编译速度,可以根据自己CPU的核心数来调整该值的大小。
make modules_install
来安装内核模块。make install
安装Linux内核。grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
//KERN_ERR是打印级别
printk(KERN_ERR "%s: kpf acpi_hest_get_size(gdata) = 0x%x, data_len = 0x%x\n", __func__, acpi_hest_get_size(gdata), data_len);
dmesg -w
即可看到添加的打印信息。存储单元
(一个存储单元可以存nbit的数据(n取决于位宽)),这个表格就叫L-BANK(逻辑Bank,也叫BANK)。
xHCI包含三个空间
主机配置空间:一般是PCI配置空间。
MMIO空间:主要放一些寄存器(Capability Registers、Operational Registers、Runtime Registers和Doorbell Array)。
主机内存:主要放一些数据结构,比如Device Context Base Address Array, Device Contexts, Transfer Ring等。
xHCI支持的传输类型:Isochronous(等时传输)、Interrupt(中断传输)、Control(控制传输)、Bulk(批量传输)。
Capability Register:这些值作为Host Controller Driver的参数。
Runtime和Operational Registers指定主机控制器配置和运行变化状态。系统软件通过该寄存器来控制和监控主机控制器的Operational状态。
xHCI Extended Capabilities说明了xHC实现的一些可选特性。
Doorbell Array:最多支持256个Doorbell寄存器的数组,每个Doorbell寄存器都向系统软件提供了一种机制,用于通知xHC是否有域槽位或者Endpoint相关的工作要执行。Doorbell寄存器的DB Target字段表示按下门铃的原因。Doorbell寄存器0被主机控制器用域Command Ring管理。
Device Slot 表示USB设备的多个XHCI数据结构。每个设备由Device Context BaseAddress Array中的一个元素、Doorbell Array register中的一个寄存器和设备的Device Context组成。Slot ID用于标识特定的Device Slot。
Command Ring:软件使用Command Ring将Command传递给xHC。
Event Ring:xHC使用Event Ring将Command Completion和Asynchronous event传递给软件。
Transfer Ring:软件使用Transfer Ring为Endpoint安排工作。Transfer Ring是一个循环队列(队列中每个元素都是是Transfer Descriptor(TD)),每个TD定义了一个或多个数据Buffer。
typedef struct _DEVICE_CONTEXT {
SLOT_CONTEXT Slot;
ENDPOINT_CONTEXT EP[31];
} DEVICE_CONTEXT;
typedef struct _SLOT_CONTEXT {
UINT32 RouteString : 20;
UINT32 Speed : 4;
UINT32 RsvdZ1 : 1;
UINT32 MTT : 1;
UINT32 Hub : 1;
UINT32 ContextEntries : 5;
UINT32 MaxExitLatency : 16;
UINT32 RootHubPortNum : 8;
UINT32 PortNum : 8;
UINT32 TTHubSlotId : 8;
UINT32 TTPortNum : 8;
UINT32 TTT : 2;
UINT32 RsvdZ2 : 4;
UINT32 InterTarget : 10;
UINT32 DeviceAddress : 8;
UINT32 RsvdZ3 : 19;
UINT32 SlotState : 5;
UINT32 RsvdZ4;
UINT32 RsvdZ5;
UINT32 RsvdZ6;
UINT32 RsvdZ7;
} SLOT_CONTEXT;
命令 | 描述 |
---|---|
No Op | 测试TRB Ring机制 |
Enable Slot | 返回设备的Slot ID并将设备Slot状态从Disabled改为Default |
Disable Slot | 将Device Slot从其他任何状态改为Disabled状态 |
Address Device | 启用Default Control Endpoint,(可选)向USB设备发出SET_ADDRESS命令并将Device Slot设置为Addressed状态 |
Configure Endpoint | 启用或者禁用设备的Enpoint |
Evaluate Context | 告知xHC软件已经修改了选定的Context参数 |
Reset Endpoint | 复位Endpoint,该命令用于将一个halted endpoint恢复 |
Stop Endpoint | 停止Endpoint |
Set TR Dequeue Pointer | 更新一个启用的endpoint的Transfer Ring Dequeue |
Reset Device | 复位Device Slot,此命令用于在复位一个USB设备时同步Device Slot的状态 |
typedef struct {
UINT8 Length; //描述符字节长度0X12
UINT8 DescriptorType; //描述符的类型
UINT16 BcdUSB; //USB设备支持的协议版本号
UINT8 DeviceClass; //设备类代码
UINT8 DeviceSubClass; //子类代码
UINT8 DeviceProtocol; //协议码
UINT8 MaxPacketSize0; //断点0的最大包长度
UINT16 IdVendor; //厂商ID
UINT16 IdProduct; //产品ID
UINT16 BcdDevice; //设备发行号
UINT8 StrManufacturer; //厂商信息的字符串描述符索引值
UINT8 StrProduct; //产品信息的字符串描述符索引值
UINT8 StrSerialNumber; //设备序列号信息的字符串描述符索引值
UINT8 NumConfigurations; //配置描述符数目
} USB_DEVICE_DESCRIPTOR;
/*
案例
------------------------------------------
Device Descriptor
bLength : 0x0012
bDescriptorType : 0x0001
bcdUSB : 0x0320 - Spec# = 03.20
bDeviceClass : 0x00 - Defined at Interface level
bDeviceSubClass : 0x00
bDeviceProtocol : 0x00
bMaxEP0Size : 0x09 - 9 bytes
idVendor : 0x0B95 - "ASIX Electronics Corp."
idProduct : 0x1790 - "AX88179 Gigabit Ethernet"
bcdDevice : 0x0200 - Device# = 02.00
iManufacturer : 0x01 - "ASIX"
iProduct : 0x02 - "AX88179A"
iSerialNumber : 0x03 - "00F30573"
bNumConfigurations : 0x03
------------------------------------------
*/
/**
@retval EFI_SUCCESS The event indicated by Index was signaled.
@retval EFI_INVALID_PARAMETER 1. NumberOfEvents is 0; 2. The event indicated by Index is of type EVT_NOTIFY_SIGNAL.
@retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_WAIT_FOR_EVENT)(
IN UINTN NumberOfEvents, //event数组的长度
IN EFI_EVENT *Event, //event数组
OUT UINTN *Index //返回触发事件的下标
);
/**
@retval EFI_SUCCESS The event structure was created.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The event could not be allocated.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_CREATE_EVENT)(
IN UINT32 Type, //事件类型
IN EFI_TPL NotifyTpl, //Notification函数的优先级
IN EFI_EVENT_NOTIFY NotifyFunction, //Notification函数
IN VOID *NotifyContext, //传给Notification函数的参数
OUT EFI_EVENT *Event //生成的事件
);
类型 | 特征 |
---|---|
EVT_TIMER | 定时器事件,没有Notification函数,生成事件后需要调用setTimer服务设置时钟属性。事件可以通过SetTimer设置等待事件、到期后通过SignalEvent触发、通过WaitForEvent等待事件触发、通过CheckEvent检查事件 |
EVT_NOTIFY_WAIT | 有一个Notification函数,当调用CheckEvent或WaitForEvent时,Notifyication函数会被放到待执行队列 |
EVT_NOTIFY_SIGNAL | 有一个Notification函数,当前事件通过SignalEvent被触发时,这个Notification函数会被放到待执行队列 |
0X00000000 | 没有Notification函数,事件可以通过signalevent触发、waitforevent等待事件被触发、checkevent检查状态 |
优先级 | 用法 | 函数 |
---|---|---|
TPL_APPLICATION | 优先级最低,当程序运行在此级别时,任务队列中没有任何处于就绪状态的Notification函数 | 下列安徽念书运行在此级别ExitBootServices()、WaitForEvent()等 |
TPL_CALLBACK | 比较耗时的操作通常在这个优先级 | Serial I/O Protocol、UnloadImage |
TPL_NOTIFY | 运行在这个级别的程序不允许阻塞,大部分Event的Notification函数允许在这个级别 | Memory Allocation Services、HII Protocols |
TPL_HIGH_LEVEL | UEFI内核全局变量的修改允许在这个级别 | SignalEvent、stall |
typedef
VOID
(EFIAPI *EFI_EVENT_NOTIFY)(
IN EFI_EVENT Event, //拥有此函数的事件
IN VOID *Context //上下文指针,在CreateEvent设置
);
/**
@retval EFI_SUCCESS The event structure was created.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The event could not be allocated.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_CREATE_EVENT_EX)(
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
IN CONST VOID *NotifyContext OPTIONAL,
IN CONST EFI_GUID *EventGroup OPTIONAL, //事件组
OUT EFI_EVENT *Event
);
/**
@retval EFI_SUCCESS 事件是触发态
@retval EFI_NOT_READY 事件是非触发态
@retval EFI_INVALID_PARAMETER 事件类型是EVT_NOTIFY_SIGNAL
**/
typedef
EFI_STATUS
(EFIAPI *EFI_CHECK_EVENT)(
IN EFI_EVENT Event
);
typedef
EFI_STATUS
(EFIAPI *EFI_SIGNAL_EVENT)(
IN EFI_EVENT Event
);
typedef
EFI_STATUS
(EFIAPI *EFI_CLOSE_EVENT)(
IN EFI_EVENT Event
);
/**
@retval EFI_SUCCESS The event has been set to be signaled at the requested time.
@retval EFI_INVALID_PARAMETER Event or Type is not valid.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_SET_TIMER)(
IN EFI_EVENT Event,
IN EFI_TIMER_DELAY Type, //定时器类型
IN UINT64 TriggerTime //过期事件,100ns为一个单位
);
类型 | |
---|---|
TimerCancel | 取消定时器触发 |
TimerPeriodic | 重复型定时器 |
TimerRelative | 一次性定时器 |
*(char(*)[4096])bitmap