Skip to content

Commit fa33195

Browse files
LPC bus sniffer program
1 parent f5b3485 commit fa33195

File tree

3 files changed

+142
-1
lines changed

3 files changed

+142
-1
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ Thank you for considering [supporting my work!](#you-can-support-my-work)
2626

2727
I usually use old or junk parts on my projects to reduce electronic waste and support the SDGs. I was working on a project to reuse an x86-based firewall that I came across in an online auction. And I found myself reading BIOS post-codes. I thought it would be a good opportunity to talk about how the LPC bus and I/O cycles work by making a BIOS POST code reader project. So, here we are.
2828

29+
### Features / Fixes
30+
31+
- LPC bus sniffer
32+
- POST code output to USB CDC
33+
2934
### Compilation
3035

3136
1. Clone the repo as shown below, or [download latest release](https://github.com/MrGreensWorkshop/RasPiPicoSDK-PicoBiosPostCodeReader/releases/latest).

src/lpc_bus_sniffer.pio

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
.program lpc_bus_sniffer
2+
;.side_set 1 opt ; [DEBUG] side_set <count> (opt) (pindirs)
3+
4+
.define NIBBLE_LOOP_COUNT 6
5+
6+
pull ; Get the filter from TX FIFO to the OSR.
7+
mov Y, OSR ; Copy OSR to Y.
8+
.wrap_target
9+
entry_point:
10+
mov ISR, null ; Clean the ISR.
11+
set X, (NIBBLE_LOOP_COUNT - 1) ; Set the value to X register.
12+
wait 0 pin 5 ; Wait until the LFRAME pin goes low.
13+
14+
; Get 6 nibble (START + CY/DR + ADDR[3-0])
15+
read_nibble1:
16+
wait 0 pin 4 ; Wait until the LCLK pin goes low.
17+
in pins, 4 ; Read the LAD[0-3] pins.
18+
wait 1 pin 4 ; Wait until the LCLK pin goes high.
19+
jmp X-- read_nibble1 ; If X is not equal to zero, decrement it and jump.
20+
21+
; Check the frame, START + CY/DR + ADDR[0-3]
22+
mov X, ISR ; Copy ISR to X.
23+
jmp X!=Y entry_point ; If X and Y registers are not equal jump.
24+
25+
; Get 1 nibble (DATA[0])
26+
wait 0 pin 4 ; Wait until the LCLK pin goes low.
27+
in pins, 4 ; Get the DATA[0].
28+
wait 1 pin 4 ; Wait until the LCLK pin goes high.
29+
30+
; Get 1 nibble (DATA[1])
31+
wait 0 pin 4 ; Wait until the LCLK pin goes low.
32+
in pins, 4 ; Get the DATA[1].
33+
wait 1 pin 4 ; Wait until the LCLK pin goes high.
34+
35+
in null, 24 ; Shift the ISR 24 bit to get DATA.
36+
push ; Push to get the DATA value on terminal.
37+
.wrap
38+
39+
% c-sdk {
40+
41+
//#define SIDE_PIN 26 // For debugging
42+
43+
void lpc_bus_sniffer_program_init(PIO pio, uint sm, uint offset, uint lpc_bus_pin_base) {
44+
pio_sm_config c = lpc_bus_sniffer_program_get_default_config(offset);
45+
46+
// Connect the GPIOs to selected PIO block
47+
for(uint i = lpc_bus_pin_base; i < lpc_bus_pin_base + 6; i++) {
48+
pio_gpio_init(pio, i);
49+
}
50+
51+
#ifdef SIDE_PIN
52+
pio_gpio_init(pio, SIDE_PIN);
53+
#endif
54+
55+
// Set the selected pin directions for the selected 6 pins. LAD[0-3] + LCLK + LFRAME (false: in)
56+
pio_sm_set_consecutive_pindirs(pio, sm, lpc_bus_pin_base, 6, false);
57+
58+
#ifdef SIDE_PIN
59+
// Set the selected pin direction for the selected 1 pin. SIDE_PIN (true: out)
60+
pio_sm_set_consecutive_pindirs(pio, sm, SIDE_PIN, 1, true );
61+
#endif
62+
63+
sm_config_set_in_shift(
64+
&c,
65+
true, // ShiftDir : true: shift ISR to right, false: shift ISR to left
66+
false, // AutoPush : true: enabled, false: disabled
67+
0 // AutoPush threshold: <0-32>
68+
);
69+
70+
sm_config_set_out_shift(
71+
&c,
72+
true, // ShiftDir : true: shift OSR to right, false: shift OSR to left
73+
false, // AutoPull : true: enabled, false: disabled
74+
0 // AutoPull threshold: <0-32>
75+
);
76+
77+
// Set 'IN' base pin. To read the LAD[0-3].
78+
sm_config_set_in_pins(&c, lpc_bus_pin_base);
79+
80+
#ifdef SIDE_PIN
81+
// Set 'SIDESET' base pin. It's for debugging.
82+
sm_config_set_sideset_pins(&c, SIDE_PIN);
83+
#endif
84+
85+
pio_sm_init(pio, sm, offset, &c);
86+
}
87+
88+
%}

src/main.c

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
#include "pico/stdlib.h"
44
#include "hardware/pio.h"
55
#include "hardware/clocks.h"
6+
#include "lpc_bus_sniffer.pio.h"
7+
8+
// Set the system frequency to 33 MHz x 6 to make time for handling LPC frames.
9+
#define SYS_FREQ_IN_KHZ (198 * 1000)
610

711
#define LED_STATUS_PIN PICO_DEFAULT_LED_PIN
812
#define INTERVAL_IM_ALIVE_MS (1000)
@@ -23,6 +27,37 @@ void flash_led_once(void) {
2327
gpio_put(LED_STATUS_PIN, 0);
2428
}
2529

30+
int init_lpc_bus_sniffer(PIO pio) {
31+
// LAD[0-3] + LCLK + LFRAME which starts from GPIO0
32+
uint lpc_bus_pin_base = 0;
33+
uint offset;
34+
35+
printf("initializing the lpc bus sniffer program\n");
36+
37+
int sm = pio_claim_unused_sm(pio, true);
38+
if(sm < 0){
39+
printf("Error: Cannot claim a free state machine\n");
40+
return -1;
41+
}
42+
43+
if (pio_can_add_program(pio, &lpc_bus_sniffer_program)) {
44+
offset = pio_add_program(pio, &lpc_bus_sniffer_program);
45+
} else {
46+
printf("Error: pio program can not be loaded\n");
47+
return -2;
48+
}
49+
50+
lpc_bus_sniffer_program_init(pio, sm, offset, lpc_bus_pin_base);
51+
pio_sm_set_enabled(pio, sm, true);
52+
53+
// To sniff the POST codes
54+
// Set the filter to I/O write cycle (0x2) and the address to 0x80.
55+
pio->txf[sm] = 0x08002000;
56+
57+
printf("program loaded at %d, sm: %d\n", offset, sm);
58+
return sm;
59+
}
60+
2661
bool repeating_timer_callback(struct repeating_timer *t) {
2762
// Print the I'm alive sign every 1 sec.
2863
printf("...\n");
@@ -33,11 +68,19 @@ int main() {
3368
// Initialize the GPIOs.
3469
gpio_initialization();
3570

71+
// Set the system frequency.
72+
set_sys_clock_khz(SYS_FREQ_IN_KHZ, true);
73+
3674
stdio_init_all();
3775
// Wait for a while. Otherwise, USB CDC doesn't print all printfs.
3876
sleep_ms(500);
3977
printf("STARTED\n");
4078

79+
// Init the PIO
80+
PIO _pio0 = pio0;
81+
int sm_lpc_bus_sniffer = init_lpc_bus_sniffer(_pio0);
82+
if (sm_lpc_bus_sniffer < 0) return -1;
83+
4184
// Print the system frequency.
4285
printf("System clock is %u kHz\n", frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS));
4386

@@ -51,5 +94,10 @@ int main() {
5194
flash_led_once();
5295
printf("Starting to sample the POST codes.\n");
5396

54-
while(1);
97+
while(1) {
98+
if (!pio_sm_is_rx_fifo_empty(_pio0, sm_lpc_bus_sniffer)) {
99+
uint32_t rxdata = _pio0->rxf[sm_lpc_bus_sniffer];
100+
printf("data: %02x\n", rxdata);
101+
}
102+
}
55103
}

0 commit comments

Comments
 (0)