SerialICE
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
October 2012
- 1 participants
- 22 discussions
New patch to review for serialice: 85ec5ab Add sample mainboard scripts
by Kyösti Mälkki Oct. 28, 2012
by Kyösti Mälkki Oct. 28, 2012
Oct. 28, 2012
Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1651
-gerrit
commit 85ec5ab0b6cfdb8da5d311e55b237f5e5179414c
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Sun Oct 28 09:51:43 2012 +0200
Add sample mainboard scripts
Scripts are written by replaying old logfiles from these platforms,
they may or may not work when used live.
Change-Id: I6510d9c82625eb6315cfd92d4a4b961a61e555a3
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
SerialICE/simba/aopen_dxpl_plus.lua | 143 ++++++++++++++++++++++++++++
SerialICE/simba/asrock_775i65g.lua | 11 +++
SerialICE/simba/asus_p4p800_vm.lua | 83 +++++++++++++++++
SerialICE/simba/conroexfire_esata2.lua | 87 +++++++++++++++++
SerialICE/simba/intel_d845gbv2.lua | 93 +++++++++++++++++++
SerialICE/simba/intel_d946gzis.lua | 78 ++++++++++++++++
SerialICE/simba/serialice.lua | 15 ++-
SerialICE/simba/via_epia_m_850.lua | 165 +++++++++++++++++++++++++++++++++
8 files changed, 673 insertions(+), 2 deletions(-)
diff --git a/SerialICE/simba/aopen_dxpl_plus.lua b/SerialICE/simba/aopen_dxpl_plus.lua
new file mode 100644
index 0000000..bc5459c
--- /dev/null
+++ b/SerialICE/simba/aopen_dxpl_plus.lua
@@ -0,0 +1,143 @@
+-- SerialICE
+--
+-- Copyright (c) 2012 Kyösti Mälkki <kyosti.malkki(a)gmail.com>
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a copy
+-- of this software and associated documentation files (the "Software"), to deal
+-- in the Software without restriction, including without limitation the rights
+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+-- copies of the Software, and to permit persons to whom the Software is
+-- furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+-- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+-- THE SOFTWARE.
+--
+
+dofile("i82801.lua")
+dofile("intel_bars.lua")
+
+-- **********************************************************
+--
+
+function mainboard_io_read(f, action)
+ -- Some timer loop
+ if ( action.addr == 0x61 ) then
+ if ( regs.eip == 0x1634 ) then
+ regs.ecx = 0x01
+ return fake_action(f, action, 0x20)
+ end
+ if ( regs.eip == 0x163a ) then
+ regs.ecx = 0x01
+ return fake_action(f, action, 0x30)
+ end
+ end
+
+ -- IO slowdown
+ if action.addr == 0xed then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ return skip_filter(f, action)
+end
+
+
+function mainboard_io_write(f, action)
+
+ -- Catch RAM controller ready.
+ if action.addr == 0x80 and action.data == 0x2c and not ram_enabled() then
+ enable_ram()
+ end
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xed then
+ if ( regs.eip == 0x1792 ) then
+ regs.ecx = 0x01
+ end
+if false then
+ -- SIPI delay
+ if ( regs.eip == 0xb3bc or regs.eip == 0xb3bf ) then
+ regs.ecx = 0x01
+ end
+ if ( regs.eip == 0xb4ad or regs.eip == 0xb4af ) then
+ regs.ecx = 0x01
+ end
+end
+ ignore_action(f, action)
+ return drop_action(f, action, action.data)
+ end
+
+ return skip_filter(f, action)
+end
+
+function mainboard_io_pre(f, action)
+ if action.write then
+ return mainboard_io_write(f, action)
+ else
+ return mainboard_io_read(f, action)
+ end
+end
+
+function mainboard_io_post(f, action)
+ if action.addr == 0xed or action.addr == 0xcfb then
+ return true
+ end
+
+ -- If KBD controller returns status=0xff, clear 0x02.
+ if action.addr == 0x64 and not action.write and action.size == 1 then
+ if action.data == 0xff then
+ -- tag these but give out correct data
+ fake_action(f, action, action.data)
+ end
+ end
+end
+
+filter_mainboard = {
+ id = -1,
+ name = "AOpen",
+ pre = mainboard_io_pre,
+ post = mainboard_io_post,
+ hide = hide_mainboard_io,
+ base = 0x0,
+ size = 0x10000
+}
+
+
+function do_mainboard_setup()
+ enable_hook(io_hooks, filter_pci_io_cfg)
+ enable_hook(mem_hooks, filter_lapic)
+ enable_hook(mem_hooks, filter_ioapic)
+
+ enable_hook(cpumsr_hooks, filter_intel_microcode)
+ enable_hook(cpuid_hooks, filter_multiprocessor)
+
+ -- I have a hook to detect RAM initialisation from
+ -- a POST code I can skip this here
+ --enable_ram()
+
+ enable_hook_pc80()
+ enable_hook_superio(0x2e, 0x07)
+ --enable_hook(io_hooks, filter_com1)
+ enable_hook_i82801dx()
+ northbridge_e7505()
+
+ -- Apply mainboard hooks last, so they are the first ones to check
+ enable_hook(io_hooks, filter_mainboard)
+end
diff --git a/SerialICE/simba/asrock_775i65g.lua b/SerialICE/simba/asrock_775i65g.lua
new file mode 100644
index 0000000..7021554
--- /dev/null
+++ b/SerialICE/simba/asrock_775i65g.lua
@@ -0,0 +1,11 @@
+
+dofile("i82801.lua")
+
+function do_mainboard_setup()
+ do_default_setup()
+
+ enable_hook_i82801dx()
+
+ -- Apply mainboard hooks last, so they are the first ones to check
+ --enable_hook(io_hooks, filter_mainboard)
+end
diff --git a/SerialICE/simba/asus_p4p800_vm.lua b/SerialICE/simba/asus_p4p800_vm.lua
new file mode 100644
index 0000000..aad1932
--- /dev/null
+++ b/SerialICE/simba/asus_p4p800_vm.lua
@@ -0,0 +1,83 @@
+
+
+function mainboard_io_read(f, action)
+ -- Some timer loop
+ if ( action.addr == 0x61 ) then
+ if ( regs.eip == 0x1634 ) then
+ regs.ecx = 0x01
+ return fake_action(f, action, 0x20)
+ end
+ if ( regs.eip == 0x163a ) then
+ regs.ecx = 0x01
+ return fake_action(f, action, 0x30)
+ end
+ end
+
+ -- IO slowdown
+ if action.addr == 0xed then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ return skip_filter(f, action)
+end
+
+
+function mainboard_io_write(f, action)
+
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xe1 then
+ ignore_action(f, action)
+ return drop_action(f, action, action.data)
+ end
+
+ return skip_filter(f, action)
+end
+
+function mainboard_io_pre(f, action)
+ if action.write then
+ return mainboard_io_write(f, action)
+ else
+ return mainboard_io_read(f, action)
+ end
+end
+
+function mainboard_io_post(f, action)
+ if action.addr == 0xe1 or action.addr == 0xed or action.addr == 0xcfb then
+ return true
+ end
+ if action.addr == 0x80 and not action.write then
+ return true
+ end
+end
+
+filter_mainboard = {
+ id = -1,
+ name = "test",
+ pre = mainboard_io_pre,
+ post = mainboard_io_post,
+ hide = hide_mainboard_io,
+ base = 0x0,
+ size = 0x10000
+}
+
+dofile("i82801.lua")
+
+function do_mainboard_setup()
+ do_default_setup()
+
+ enable_hook_i82801dx()
+
+ -- Apply mainboard hooks last, so they are the first ones to check
+ enable_hook(io_hooks, filter_mainboard)
+end
diff --git a/SerialICE/simba/conroexfire_esata2.lua b/SerialICE/simba/conroexfire_esata2.lua
new file mode 100644
index 0000000..5f8b198
--- /dev/null
+++ b/SerialICE/simba/conroexfire_esata2.lua
@@ -0,0 +1,87 @@
+
+
+
+function mainboard_io_read(f, action)
+ -- Some timer loop
+ if ( action.addr == 0x61 ) then
+ if ( regs.eip == 0x1634 ) then
+ regs.ecx = 0x01
+ return fake_action(f, action, 0x20)
+ end
+ if ( regs.eip == 0x163a ) then
+ regs.ecx = 0x01
+ return fake_action(f, action, 0x30)
+ end
+ end
+
+ -- IO slowdown
+ if action.addr == 0xed then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ return skip_filter(f, action)
+end
+
+
+function mainboard_io_write(f, action)
+
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xe1 then
+ ignore_action(f, action)
+ return drop_action(f, action, action.data)
+ end
+
+ return skip_filter(f, action)
+end
+
+function mainboard_io_pre(f, action)
+ if action.write then
+ return mainboard_io_write(f, action)
+ else
+ return mainboard_io_read(f, action)
+ end
+end
+
+function mainboard_io_post(f, action)
+ if action.addr == 0xe1 or action.addr == 0xed or action.addr == 0xcfb then
+ return true
+ end
+ if action.addr == 0x80 and not action.write then
+ return true
+ end
+end
+
+filter_mainboard = {
+ id = -1,
+ name = "test",
+ pre = mainboard_io_pre,
+ post = mainboard_io_post,
+ hide = hide_mainboard_io,
+ base = 0x0,
+ size = 0x10000
+}
+
+dofile("i82801.lua")
+dofile("intel_bars.lua")
+
+function do_mainboard_setup()
+ do_default_setup()
+
+ enable_hook_i82801gx()
+
+ northbridge_i945()
+
+ -- Apply mainboard hooks last, so they are the first ones to check
+ enable_hook(io_hooks, filter_mainboard)
+end
diff --git a/SerialICE/simba/intel_d845gbv2.lua b/SerialICE/simba/intel_d845gbv2.lua
new file mode 100644
index 0000000..43921ee
--- /dev/null
+++ b/SerialICE/simba/intel_d845gbv2.lua
@@ -0,0 +1,93 @@
+
+
+function mainboard_io_read(f, action)
+ -- Some timer loop
+ if ( action.addr == 0x61 ) then
+ end
+
+ -- IO slowdown
+ if action.addr == 0xed then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ return skip_filter(f, action)
+end
+
+
+function mainboard_io_write(f, action)
+
+ -- Catch RAM controller ready.
+ if action.addr == 0x80 and action.data == 0xd5 and not ram_enabled() then
+ -- enable_ram()
+ end
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xe1 then
+ ignore_action(f, action)
+ return drop_action(f, action, action.data)
+ end
+
+ return skip_filter(f, action)
+end
+
+function mainboard_io_pre(f, action)
+ if action.write then
+ return mainboard_io_write(f, action)
+ else
+ return mainboard_io_read(f, action)
+ end
+end
+
+function mainboard_io_post(f, action)
+ if action.addr == 0xe1 or action.addr == 0xed or action.addr == 0xcfb then
+ return true
+ end
+ if action.addr == 0x80 and not action.write then
+ return true
+ end
+end
+
+filter_mainboard = {
+ id = -1,
+ name = "GEBV2",
+ pre = mainboard_io_pre,
+ post = mainboard_io_post,
+ hide = hide_mainboard_io,
+ base = 0x0,
+ size = 0x10000
+}
+
+dofile("i82801.lua")
+
+function do_mainboard_setup()
+ new_car_region(0xfef00000, 0x800)
+
+ enable_hook(io_hooks, filter_pci_io_cfg)
+ enable_hook(mem_hooks, filter_lapic)
+ enable_hook(mem_hooks, filter_ioapic)
+
+ enable_hook(cpumsr_hooks, filter_intel_microcode)
+ enable_hook(cpuid_hooks, filter_multiprocessor)
+
+ -- I have a hook to detect RAM initialisation from
+ -- a POST code I can skip this here
+ enable_ram()
+
+ enable_hook_pc80()
+ enable_hook_superio(0x2e, 0x07)
+ --enable_hook(io_hooks, filter_com1)
+ enable_hook_i82801dx()
+
+ -- Apply mainboard hooks last, so they are the first ones to check
+ enable_hook(io_hooks, filter_mainboard)
+end
diff --git a/SerialICE/simba/intel_d946gzis.lua b/SerialICE/simba/intel_d946gzis.lua
new file mode 100644
index 0000000..ea46ba3
--- /dev/null
+++ b/SerialICE/simba/intel_d946gzis.lua
@@ -0,0 +1,78 @@
+
+
+
+function mainboard_io_read(f, action)
+ -- IO slowdown
+ if action.addr == 0xed then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ return skip_filter(f, action)
+end
+
+
+function mainboard_io_write(f, action)
+
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xe1 then
+ ignore_action(f, action)
+ return drop_action(f, action, action.data)
+ end
+
+ return skip_filter(f, action)
+end
+
+function mainboard_io_pre(f, action)
+ if action.write then
+ return mainboard_io_write(f, action)
+ else
+ return mainboard_io_read(f, action)
+ end
+end
+
+function mainboard_io_post(f, action)
+ if action.addr == 0xe1 or action.addr == 0xed or action.addr == 0xcfb then
+ return true
+ end
+ if action.addr == 0x80 and not action.write then
+ return true
+ end
+end
+
+filter_mainboard = {
+ id = -1,
+ name = "test",
+ pre = mainboard_io_pre,
+ post = mainboard_io_post,
+ hide = hide_mainboard_io,
+ base = 0x0,
+ size = 0x10000
+}
+
+dofile("i82801.lua")
+dofile("intel_bars.lua")
+
+function do_mainboard_setup()
+ do_default_setup()
+
+ enable_hook_i82801gx()
+ enable_hook(cpumsr_hooks, filter_intel_microcode)
+ enable_hook(cpuid_hooks, filter_multiprocessor)
+ northbridge_i946()
+
+ new_car_region(0xfef00000,0x2000)
+
+ -- Apply mainboard hooks last, so they are the first ones to check
+ enable_hook(io_hooks, filter_mainboard)
+end
diff --git a/SerialICE/simba/serialice.lua b/SerialICE/simba/serialice.lua
index 9d2f672..9eb287d 100644
--- a/SerialICE/simba/serialice.lua
+++ b/SerialICE/simba/serialice.lua
@@ -36,6 +36,7 @@ hide_i8254_io = true
hide_i8259_io = true
hide_superio_cfg = true
hide_smbus_io = true
+hide_mainboard_io = true
-- Set to "true" to log every memory and IO access
log_everything = false
@@ -90,8 +91,18 @@ function do_default_setup()
end
end
-do_minimal_setup()
-do_default_setup()
+mainboard_file = string.format("%s.lua", string.lower(string.gsub(SerialICE_mainboard, "[ -]", "_")))
+local mainboard_lua = loadfile(mainboard_file)
+if (mainboard_lua) then
+ mainboard_lua()
+ printks(froot, "Mainboard script %s initialized.\n", mainboard_file)
+ do_minimal_setup()
+ do_mainboard_setup()
+else
+ printks(froot, "Mainboard script %s not found.\n", mainboard_file)
+ do_minimal_setup()
+ do_default_setup()
+end
printks(froot, "LUA script initialized.\n")
diff --git a/SerialICE/simba/via_epia_m_850.lua b/SerialICE/simba/via_epia_m_850.lua
new file mode 100644
index 0000000..e4649c4
--- /dev/null
+++ b/SerialICE/simba/via_epia_m_850.lua
@@ -0,0 +1,165 @@
+-- SerialICE
+--
+-- Copyright (c) 2012 Kyösti Mälkki <kyosti.malkki(a)gmail.com>
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a copy
+-- of this software and associated documentation files (the "Software"), to deal
+-- in the Software without restriction, including without limitation the rights
+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+-- copies of the Software, and to permit persons to whom the Software is
+-- furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+-- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+-- THE SOFTWARE.
+--
+
+
+-- **********************************************************
+--
+
+function mainboard_io_read(f, action)
+
+ -- IO slowdown
+ if action.addr == 0xed then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ -- IO slowdown
+ if action.addr == 0xeb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ if action.addr == 0xcfb then
+ ignore_action(f, action)
+ return drop_action(f, action, 0)
+ end
+
+ return skip_filter(f, action)
+end
+
+
+function mainboard_io_write(f, action)
+
+ -- Catch RAM controller ready.
+ if action.addr == 0x80 and action.data == 0x2c and not ram_enabled() then
+ enable_ram()
+ end
+
+-- if action.addr == 0xcfb then
+-- ignore_action(f, action)
+-- return drop_action(f, action, 0)
+-- end
+
+ if action.addr == 0xeb then
+ ignore_action(f, action)
+ return drop_action(f, action, action.data)
+ end
+
+ if action.addr == 0xed then
+ ignore_action(f, action)
+ return drop_action(f, action, action.data)
+ end
+
+ return skip_filter(f, action)
+end
+
+function mainboard_io_pre(f, action)
+ if action.write then
+ return mainboard_io_write(f, action)
+ else
+ return mainboard_io_read(f, action)
+ end
+end
+
+function mainboard_io_post(f, action)
+ if action.addr == 0xeb or action.addr == 0xed then
+ return true
+ end
+
+ -- If KBD controller returns status=0xff, clear 0x02.
+ if action.addr == 0x64 and not action.write and action.size == 1 then
+ if action.data == 0xff then
+ -- tag these but give out correct data
+ fake_action(f, action, action.data)
+ end
+ end
+end
+
+filter_mainboard = {
+ id = -1,
+ name = "VIA",
+ pre = mainboard_io_pre,
+ post = mainboard_io_post,
+ hide = hide_mainboard_io,
+ base = 0x0,
+ size = 0x10000
+}
+
+
+
+-- MOVE THIS TO CHIPSET FILE
+
+dofile("intel_smbus.lua")
+dofile("via_bars.lua")
+
+function smbus_bar_hook(dev, reg, base)
+ intel_smbus_setup(base, 0x20)
+end
+
+dev_sb_lpc = {
+ pci_dev = pci_bdf(0x0,0x1f,0x3,0x0),
+ name = "Smbus",
+ bar = {},
+}
+
+dev_power = {
+ pci_dev = pci_bdf(0x0,0x11,0x0,0x0),
+ name = "SYS",
+ bar = {},
+ acpi = { f = nil },
+ tco = { f = nil },
+}
+
+function pm_io_bar(dev, reg, base)
+ dev.acpi.name = "ACPI"
+ dev.acpi.base = base
+ dev.acpi.size = 0x60
+ generic_io_bar(dev.acpi)
+end
+
+
+
+-- ****************
+
+function do_mainboard_setup()
+ enable_hook(io_hooks, filter_pci_io_cfg)
+ enable_hook(mem_hooks, filter_lapic)
+ enable_hook(mem_hooks, filter_ioapic)
+
+ enable_hook(cpumsr_hooks, filter_intel_microcode)
+ enable_hook(cpuid_hooks, filter_multiprocessor)
+
+ -- I have a hook to detect RAM initialisation from
+ -- a POST code I can skip this here
+ --enable_ram()
+
+ enable_hook_pc80()
+ enable_hook_superio(0x4e, 0x07)
+
+ northbridge_vx900()
+ pci_cfg16_hook(dev_power, 0x88, "PM", pm_io_bar)
+ pci_cfg16_hook(dev_power, 0xd0, "SMBus", smbus_bar_hook)
+
+ -- Apply mainboard hooks last, so they are the first ones to check
+ enable_hook(io_hooks, filter_mainboard)
+end
1
0
Oct. 28, 2012
Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1648
-gerrit
commit 562525ed1cfe0bab64520605d057fc4448a39d68
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Sun Oct 28 11:54:51 2012 +0200
Add APIC memory spaces
To be precise, the base addresses of APICs are actually configurable
in either PCI config space or an MSR. For now, this decodes at
the commonly used and fixed base address for both IOAPIC and LAPIC.
For LAPIC, Startup-IPI is replaced with INIT IPI to prevent AP CPUs
from attempting to execute code from Flash.
Change-Id: Icdbb8cd460bba440b466860f7e92f8a83cdb9d00
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
SerialICE/simba/mmio.lua | 40 ++++++++++++++++++++++++++++++++++++++++
SerialICE/simba/serialice.lua | 3 +++
2 files changed, 43 insertions(+)
diff --git a/SerialICE/simba/mmio.lua b/SerialICE/simba/mmio.lua
new file mode 100644
index 0000000..695315f
--- /dev/null
+++ b/SerialICE/simba/mmio.lua
@@ -0,0 +1,40 @@
+
+-- **********************************************************
+--
+-- Vendor independent X86 memory mapped IO
+
+-- Local APIC
+-- We should avoid that someone wakes up cores
+-- on the target system that go wild.
+function mem_lapic(f, action)
+ if bit32.band(action.addr, f.size-1) == 0x300 then
+ -- replace Start-Up IPI with Init IPI
+ if action.write and bit32.band(action.data, 0xf0f00) == 0xc0600 then
+ return fake_action(f, action, 0xc0500)
+ end
+ end
+ return handle_action(f, action)
+end
+
+filter_lapic = {
+ id = -1,
+ name = "LAPIC",
+ pre = mem_lapic,
+ post = mem_base_post,
+ hide = true,
+ base = 0xfee00000,
+ size = 0x00010000,
+}
+
+-- IOAPIC
+filter_ioapic = {
+ id = -1,
+ name = "IOAPIC",
+ pre = mem_target_only,
+ post = mem_base_post,
+ hide = true,
+ base = 0xfec00000,
+ size = 0x00010000,
+}
+
+
diff --git a/SerialICE/simba/serialice.lua b/SerialICE/simba/serialice.lua
index 3700589..08625d6 100644
--- a/SerialICE/simba/serialice.lua
+++ b/SerialICE/simba/serialice.lua
@@ -64,6 +64,7 @@ dofile("cpu.lua")
dofile("pci_cfg.lua")
dofile("pc80.lua")
dofile("superio.lua")
+dofile("mmio.lua")
function do_minimal_setup()
enable_hook(io_hooks, filter_io_fallback)
@@ -76,6 +77,8 @@ end
function do_default_setup()
enable_ram()
+ enable_hook(mem_hooks, filter_lapic)
+ enable_hook(mem_hooks, filter_ioapic)
enable_hook(io_hooks, filter_pci_io_cfg)
enable_hook_pc80()
enable_hook_superio(0x2e, DEFAULT_SUPERIO_LDN_REGISTER)
1
0
Oct. 28, 2012
Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1649
-gerrit
commit 05f592394eff03e6ec0ca51c9fd0ce39334cd2eb
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Sun Oct 28 12:19:03 2012 +0200
Add SMBus decoder
Decodes a series of IO accesses to the SMBus controller device
as a series of bytes transmitted on the SMBus.
Tested mostly on Intel ICH4, some VIA seemed to be compatible too.
Change-Id: Id5248f4d9a2d550e8fd06d4252a67a404f719b77
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
SerialICE/simba/intel_smbus.lua | 259 +++++++++++++++++++
SerialICE/simba/serialice.lua | 1 +
SerialICE/simba/smbus_host.lua | 559 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 819 insertions(+)
diff --git a/SerialICE/simba/intel_smbus.lua b/SerialICE/simba/intel_smbus.lua
new file mode 100644
index 0000000..daa0b9d
--- /dev/null
+++ b/SerialICE/simba/intel_smbus.lua
@@ -0,0 +1,259 @@
+
+
+dofile("smbus_host.lua")
+
+-- ********************************************
+-- Intel 82801 SMBus Host controller
+
+I801_SMB_HSTSTS = 0
+I801_SMB_HSTCNT = 2
+I801_SMB_HSTCMD = 3
+I801_SMB_HSTADD = 4
+I801_SMB_HSTDAT0 = 5
+I801_SMB_HSTDAT1 = 6
+I801_SMB_BLKDAT = 7
+I801_SMB_PEC = 8
+I801_SMB_AUXSTS = 12
+I801_SMB_AUXCTL = 13
+
+I801_QUICK = 0x00
+I801_BYTE = 0x04
+I801_BYTE_DATA = 0x08
+I801_WORD_DATA = 0x0C
+I801_PROC_CALL = 0x10
+I801_BLOCK_DATA = 0x14
+I801_I2C_BLOCK_DATA = 0x18
+I801_BLOCK_PROCESS = 0x1C
+I801_BLOCK_LAST = 0x34 -- 0x14 | 0x20
+I801_I2C_BLOCK_LAST = 0x38 -- 0x18 | 0x20
+I801_START = 0x40
+I801_PEC_EN = 0x80
+
+
+local function intel_smbus_get_protocol(f)
+ local proto = bit32.band(f.reg.control, 0x1c)
+
+ if proto == I801_QUICK then
+ return SMBUS_QUICK
+
+ elseif proto == I801_BYTE then
+ return SMBUS_BYTE
+
+ elseif proto == I801_BYTE_DATA then
+ return SMBUS_BYTE_DATA
+
+ elseif proto == I801_WORD_DATA then
+ return SMBUS_WORD_DATA
+
+ elseif proto == I801_PROC_CALL then
+ return SMBUS_PROC_CALL
+
+ elseif proto == I801_BLOCK_DATA then
+ return SMBUS_BLOCK_DATA
+
+ elseif proto == I801_I2C_BLOCK_DATA then
+ return SMBUS_I2C_BLOCK_DATA
+
+ elseif proto == I801_BLOCK_PROCESS then
+ return SMBUS_BLOCK_PROCESS
+
+ else
+ printk(f, action, "Unknown protocol\n")
+ return SMBUS_NOOP
+ end
+end
+
+local function intel_smbus_host_status(f, action)
+ if not action.write then
+ if smbus.passive(f) then
+ f.reg.status = action.data;
+ end
+
+ if smbus.state(f, HOST_IDLE) then
+ if not smbus.passive(f) then
+ f.reg.status = 0x0
+ end
+ if bit32.band(f.reg.status, 0x40) ~= 0 then
+ printk(f, action, "Host may be busy, ignoring.\n")
+ end
+ smbus.get_resource(f)
+
+ elseif smbus.state(f, HOST_ACTIVE) then
+ f.reg.busy_count = 3
+
+ elseif smbus.state(f, HOST_STARTED) then
+ if not smbus.passive(f) then
+ f.reg.status = bit32.band(f.reg.status, 0xFE)
+ if f.reg.busy_count > 0 then
+ f.reg.busy_count = f.reg.busy_count - 1
+ f.reg.status = bit32.bor(f.reg.status, 0x01)
+ end
+ if bit32.band(f.reg.status, 0x02) == 0 then
+ smbus_transaction(host)
+ end
+ end
+
+ local irq = bit32.band(f.reg.status, 0x02) ~= 0
+ local failures = bit32.band(f.reg.status, 0x1c) ~= 0
+ local host_busy = bit32.band(f.reg.status, 0x01) ~= 0
+
+ if irq and not host_busy then
+ smbus.done(f)
+ end
+ if failures then
+ smbus.timeout(f)
+ end
+ end
+
+ if not smbus.passive(f) then
+ action.data = f.reg.status;
+ f.reg.status = bit32.bor(f.reg.status, 0x40)
+ end
+ else
+
+ if not smbus.passive(f) then
+ f.reg.status = bit32.band(f.reg.status, bit32.bnot(action.data))
+ end
+
+ local ack_irq = bit32.band(action.data, 0x02) ~= 0
+ local release_host = bit32.band(action.data, 0x40) ~= 0
+ local failures = bit32.band(action.data, 0x1c) ~= 0
+ if release_host then
+ smbus.put_resource(f)
+ end
+ if failures then
+ smbus.timeout_ack(f)
+ end
+ if ack_irq then
+ smbus.ack(f)
+ end
+ end
+
+end
+
+
+local function intel_smbus_host_control(f, action)
+
+ if not action.write then
+ f.reg.block_ptr=0;
+ if not smbus.passive(f) then
+ action.data = bit32.band(f.reg.control, bit32.bnot(0x40))
+ end
+
+ else
+
+ f.reg.control = action.data;
+ if bit32.band(f.reg.control, 0x80) ~= 0 then
+ printk(f, action, "No PEC simulation\n")
+ end
+
+ local abort = bit32.band(f.reg.control, 0x02) ~= 0
+ local start = bit32.band(f.reg.control, 0x40) ~= 0
+ if abort then
+ smbus.abort(f)
+ end
+ if start then
+ f.reg.block_ptr=0;
+ smbus.update_register(f, action, SMB_REG_PROTO)
+ smbus.start(f, intel_smbus_get_protocol(f))
+ end
+ end
+end
+
+
+
+local function intel_smbus_block_data(f, action)
+ if f.reg.block_ptr < MAX_BLOCK_SRAM then
+ smbus.block_data(f, action, f.reg.block_ptr)
+ end
+ f.reg.block_ptr = f.reg.block_ptr + 1
+ smbus.update_register(f, action, SMB_REG_BLOCK)
+end
+
+local function intel_smbus_host_access(f, action)
+ local reg = bit32.band(action.addr, (f.size-1))
+
+ -- mirror hw register both ways
+ local data_write = 0
+
+ -- Store this to display CS:IP etc.
+ f.host.action = action
+
+ if reg == I801_SMB_HSTSTS then
+ intel_smbus_host_status(f, action);
+
+ elseif reg == I801_SMB_HSTCNT then
+ intel_smbus_host_control(f, action);
+
+ elseif reg == I801_SMB_HSTCMD then
+ smbus.update_register(f, action, SMB_REG_CMD)
+
+ elseif reg == I801_SMB_HSTADD then
+ smbus.update_register(f, action, SMB_REG_SLAVE)
+
+ elseif reg == I801_SMB_HSTDAT0 then
+ smbus.update_register(f, action, SMB_REG_DATA0)
+
+ elseif reg == I801_SMB_HSTDAT1 then
+ smbus.update_register(f, action, SMB_REG_DATA1)
+
+ elseif reg == I801_SMB_BLKDAT then
+ intel_smbus_block_data(f, action);
+
+ elseif reg == I801_SMB_AUXSTS then
+ if data_write then
+ f.reg.aux_sts = action.data;
+ else
+ action.data = f.reg.aux_sts;
+ end
+
+ elseif reg == I801_SMB_AUXCTL then
+ if data_write then
+ f.reg.aux_ctl = action.data;
+ else
+ action.data = f.reg.aux_ctl;
+ end
+
+ else
+ printk(f, action, "Unknown register 0x%02x\n", reg);
+ end
+end
+
+
+function intel_smbus_host_pre(f, action)
+ if action.write then
+ intel_smbus_host_access(f, action)
+ end
+ return handle_action(f, action)
+end
+
+function intel_smbus_host_post(f, action)
+ if not action.write then
+ intel_smbus_host_access(f, action)
+ end
+ return true
+end
+
+
+local intel_smbus_host = {
+ id = -1,
+ name = "i801-smbus",
+ pre = intel_smbus_host_pre,
+ post = intel_smbus_host_post,
+ hide = hide_smbus_io,
+ base = 0x0,
+ size = 0x0,
+}
+
+function intel_smbus_setup(base, size)
+ local f = intel_smbus_host
+ f.base = bit32.band(base, bit32.bnot(size-1))
+ f.size = size
+ if not f.reg then
+ f.reg = { control = 0, status = 0, busy_count = 0, block_ptr = 0, aux_ctl = 0, aux_sts = 0 }
+ end
+ smbus.init(f)
+
+ enable_hook(io_hooks, f)
+end
+
diff --git a/SerialICE/simba/serialice.lua b/SerialICE/simba/serialice.lua
index 08625d6..9d2f672 100644
--- a/SerialICE/simba/serialice.lua
+++ b/SerialICE/simba/serialice.lua
@@ -35,6 +35,7 @@ hide_i8237_io = true
hide_i8254_io = true
hide_i8259_io = true
hide_superio_cfg = true
+hide_smbus_io = true
-- Set to "true" to log every memory and IO access
log_everything = false
diff --git a/SerialICE/simba/smbus_host.lua b/SerialICE/simba/smbus_host.lua
new file mode 100644
index 0000000..a407843
--- /dev/null
+++ b/SerialICE/simba/smbus_host.lua
@@ -0,0 +1,559 @@
+
+
+local debug_smbus = false
+smbus = {}
+
+smbus.host = {
+ state = { current = 0, jump_to = 0 },
+ proto = 0,
+ start_proto = 0,
+
+ passive = true,
+ signals = 0,
+
+ slave = 0,
+ cmd = 0,
+ data0 = 0,
+ data1 = 0,
+ data0_valid = false,
+ data1_valid = false,
+ wr_data0 = 0,
+ wr_data1 = 0,
+ block_register = 0,
+
+ block = {},
+ max_index = 0,
+}
+
+MAX_BLOCK_SRAM = 32
+
+if true then
+ for i = 0, MAX_BLOCK_SRAM-1, 1 do
+ smbus.host.block[i] = { hw = 0, tmp = 0, hw_valid = false, tmp_valid = false }
+ end
+end
+
+-- *******************
+
+SIG_INUSE = 0
+SIG_RELEASE = 1
+SIG_START = 2
+SIG_ABORT = 3
+SIG_DONE = 4
+SIG_ACK = 5
+SIG_TIMEOUT = 6
+SIG_TIMEOUT_ACK = 7
+SIG_DATA_WRITE = 8
+
+local function signal_reset(f)
+ f.host.signals = 0
+end
+
+local function signal_set(f, flag)
+ local mask = bit32.lshift(1, flag)
+ f.host.signals = bit32.bor(f.host.signals, mask)
+end
+
+local function signal_clr(f, flag)
+ local mask = bit32.bnot(bit32.lshift(1, flag))
+ f.host.signals = bit32.band(f.host.signals, mask)
+
+end
+
+local function signal_in(f, flag)
+ local mask = bit32.lshift(1, flag)
+ return bit32.band(f.host.signals, mask) ~= 0
+end
+
+-- *******************
+
+-- SMBus Protocol Message Types
+SMBUS_NOOP = 0
+SMBUS_QUICK = 1
+SMBUS_BYTE = 2
+SMBUS_BYTE_DATA = 3
+SMBUS_WORD_DATA = 4
+SMBUS_PROC_CALL = 5
+SMBUS_BLOCK_DATA = 6
+SMBUS_I2C_BLOCK_DATA = 7
+SMBUS_BLOCK_PROCESS = 8
+
+local proto_name = {}
+proto_name[SMBUS_NOOP] = "(no-op)"
+proto_name[SMBUS_QUICK] = "quick"
+proto_name[SMBUS_BYTE] = "byte"
+proto_name[SMBUS_BYTE_DATA] = "byte_data"
+proto_name[SMBUS_WORD_DATA] = "word_data"
+proto_name[SMBUS_PROC_CALL] = "proc_call"
+proto_name[SMBUS_BLOCK_DATA] = "block"
+proto_name[SMBUS_I2C_BLOCK_DATA] = "i2c_block"
+proto_name[SMBUS_BLOCK_PROCESS] = "block_process"
+
+-- SMBus Host
+SMB_REG_CMD = 1
+SMB_REG_SLAVE = 2
+SMB_REG_DATA0 = 3
+SMB_REG_DATA1 = 4
+SMB_REG_BLOCK = 5
+SMB_REG_PROTO = 6
+
+
+local function dump_block(f, length)
+ local block = ""
+ local max_length = math.min(length, MAX_BLOCK_SRAM)
+
+ for i=0, max_length-1, 1 do
+ if f.host.block[i].hw_valid then
+ block = block .. string.format(" %02x", f.host.block[i].hw)
+ else
+ block = block .. " xx"
+ end
+ end
+ return block
+end
+
+
+-- FIXME: Probably wrong for process calls and hw-dependent.
+local function host_proto(f, proto)
+ return f.host.proto == proto
+end
+
+local function host_reading(f)
+ return bit32.band(f.host.slave, 0x01) == 0x01
+end
+
+
+
+local function dump_transaction(f, action)
+
+ local data0, data1, length, dir
+ local invalid_data = "xx"
+ local iodir = {}
+ iodir[0] = "<="
+ iodir[1] = "=>"
+
+ if host_reading(f) then
+ dir = iodir[1]
+ data0 = invalid_data
+ length = f.host.max_index
+ if f.host.data0_valid then
+ length = f.host.data0
+ data0 = string.format("%02x", f.host.data0)
+ end
+ data1 = invalid_data
+ if f.host.data1_valid then
+ data1 = string.format("%02x", f.host.data1)
+ end
+ else
+ dir = iodir[0]
+ length = f.host.wr_data0
+ data0 = string.format("%02x", f.host.wr_data0)
+ data1 = string.format("%02x", f.host.wr_data1)
+ end
+
+
+ local dump = string.format("%02x %s ", f.host.slave / 2, proto_name[f.host.proto])
+
+ if host_proto(f, SMBUS_QUICK) then
+
+ elseif host_proto(f, SMBUS_BYTE) then
+ dump = dump .. string.format("%02x %s %s", f.host.cmd, dir, data0)
+
+ elseif host_proto(f, SMBUS_BYTE_DATA) then
+ dump = dump .. string.format("%02x %s %s", f.host.cmd, dir, data0)
+
+ elseif host_proto(f, SMBUS_WORD_DATA) then
+ dump = dump .. string.format("%02x %s %s%s", f.host.cmd, dir, data0, data1)
+
+ elseif host_proto(f, SMBUS_PROC_CALL) then
+ dump = dump .. string.format("%02x %02x %02x %s %s %s", f.host.cmd,
+ f.host.wr_data0, f.host.wr_data1, iodir[1], data0, data1)
+
+ elseif host_proto(f, SMBUS_BLOCK_DATA) then
+ dump = dump .. string.format("%02x len=%02d %s", f.host.cmd, length, dir)
+ dump = dump .. dump_block(f, length) .. ""
+
+ elseif host_proto(f, SMBUS_I2C_BLOCK_DATA) then
+ dump = dump .. string.format("%02x %02x %02x len=%02d %s",
+ f.host.cmd, f.host.data0, f.host.data1, f.host.max_index, dir)
+ dump = dump .. dump_block(f, length) .. ""
+
+ elseif host_proto(f, SMBUS_BLOCK_PROCESS) then
+ dump = dump .. string.format("%02x len=%02d %s", f.host.cmd, length, iodir[1])
+ dump = dump .. dump_block(f, length) .. ""
+ else
+ dump = dump .. "Cannot parse command"
+ end
+
+ if signal_in(f, SIG_TIMEOUT) then
+ action.undefined = true
+ dump = dump .. " (TIMEOUT) "
+ end
+
+ printk(f, action, "%s\n", dump)
+end
+
+
+-- *******************
+
+HOST_NOOP = 0
+HOST_IDLE = 1
+HOST_ACTIVE = 2
+HOST_STARTED = 3
+HOST_WAIT = 4
+HOST_COMPLETE = 5
+HOST_FAIL = 6
+
+local ctrl_state = {}
+ctrl_state[HOST_NOOP] = "noop"
+ctrl_state[HOST_IDLE] = "idle"
+ctrl_state[HOST_ACTIVE] = "active"
+ctrl_state[HOST_STARTED] = "started"
+ctrl_state[HOST_WAIT] = "wait"
+ctrl_state[HOST_COMPLETE] = "complete"
+ctrl_state[HOST_FAIL] = "failed"
+
+function dprintk(...)
+ if debug_smbus then
+ printk(...)
+ end
+end
+
+local function host_jump(f, state)
+ f.host.state.jump_to = state
+end
+
+local function host_change_state(f, prev_state, new_state)
+
+ if new_state == HOST_NOOP then
+ --printk(f, f.host.action, "state switch to HOST_NOOP\n")
+ new_state = HOST_IDLE
+ end
+
+ dprintk(f, f.host.action, "%s -> %s\n",
+ ctrl_state[prev_state], ctrl_state[new_state])
+
+ -- Jumping to current is no jump.
+ f.host.state.current = new_state
+ f.host.state.jump_to = new_state
+
+ if smbus.state(f, HOST_IDLE) then
+ signal_reset(f)
+
+ elseif smbus.state(f, HOST_ACTIVE) then
+ signal_reset(f)
+ signal_set(f, SIG_INUSE)
+
+ elseif smbus.state(f, HOST_STARTED) then
+ local i
+ f.host.proto = f.host.start_proto
+ f.host.wr_data0 = f.host.data0
+ f.host.wr_data1 = f.host.data1
+
+ -- Invalidation used with reads
+ f.host.data0_valid = false
+ f.host.data1_valid = false
+
+ for i = 0, MAX_BLOCK_SRAM-1, 1 do
+ f.host.max_index = 0
+ -- On block writes, previously read data in buffer is also valid.
+ if f.host.block[i].tmp_valid then
+ f.host.block[i].hw = f.host.block[i].tmp
+ f.host.block[i].tmp_valid = false
+ f.host.block[i].hw_valid = true
+ end
+ -- On block reads, no data in buffer is yet valid.
+ if host_reading(f) and host_proto(f, SMBUS_BLOCK_DATA) then
+ f.host.block[i].hw_valid = false;
+ end
+ end
+
+ elseif smbus.state(f, HOST_COMPLETE) then
+ dump_transaction(f, f.host.action)
+ if signal_in(f, SIG_RELEASE) then
+ host_jump(f, HOST_IDLE)
+ else
+ host_jump(f, HOST_ACTIVE)
+ end
+
+-- elseif smbus.state(f, HOST_FAIL) then
+-- dump_transaction(f, f.host.action)
+-- host_jump(f, HOST_ACTIVE)
+ end
+
+end
+
+local function host_switch(f, new_state)
+ local prev_state = f.host.state.current
+ while prev_state ~= new_state do
+ host_change_state(f, prev_state, new_state)
+ prev_state = f.host.state.current
+ new_state = f.host.state.jump_to
+ end
+end
+
+local function host_read_completed(f)
+
+ if not host_reading(f) then
+ return true
+ end
+
+ local complete = false
+
+ if host_proto(f, SMBUS_QUICK) then
+ complete = true
+
+ elseif host_proto(f, SMBUS_BYTE) then
+ complete = f.host.data0_valid
+
+ elseif host_proto(f, SMBUS_BYTE_DATA) then
+ complete = f.host.data0_valid
+
+ elseif host_proto(f, SMBUS_WORD_DATA) then
+ complete = f.host.data0_valid and f.host.data1_valid
+
+ elseif host_proto(f, SMBUS_BLOCK_DATA) then
+ complete = f.host.data0_valid and f.host.max_index >= f.host.data0
+
+ elseif host_proto(f, SMBUS_PROC_CALL) or host_proto(f, SMBUS_I2C_BLOCK_DATA)
+ or host_proto(f, SMBUS_BLOCK_PROCESS) then
+ printk(f, f.host.action, "Unimplemented completion (proto %d)\n", f.host.proto)
+ end
+ return complete
+end
+
+
+-- Syncronize state machine according to input signals.
+local function host_sync(f)
+
+-- if release and not smbus.state(f, HOST_ACTIVE) then
+-- printk(f, f.host.action, "Premature reset of bit INUSE_STS\n")
+-- end
+ if signal_in(f, SIG_ABORT) then
+ -- FIXME Killing on-going transaction.
+ host_switch(f, HOST_COMPLETE)
+ end
+
+ if smbus.state(f, HOST_IDLE) then
+ if signal_in(f, SIG_INUSE) then
+ host_switch(f, HOST_ACTIVE)
+ end
+ if signal_in(f, SIG_START) then
+ host_switch(f, HOST_STARTED)
+ end
+
+ elseif smbus.state(f, HOST_ACTIVE) then
+ if signal_in(f, SIG_START) then
+ host_switch(f, HOST_STARTED)
+ end
+
+ elseif smbus.state(f, HOST_STARTED) then
+ if signal_in(f, SIG_TIMEOUT) then
+ host_switch(f, HOST_FAIL)
+ elseif signal_in(f, SIG_DONE) then
+ host_switch(f, HOST_WAIT)
+ end
+
+ elseif smbus.state(f, HOST_WAIT) then
+ if signal_in(f, SIG_START) then
+ -- Restarting previous transaction.
+ host_switch(f, HOST_COMPLETE)
+ host_switch(f, HOST_STARTED)
+ elseif signal_in(f, SIG_ACK) and not host_reading(f) then
+ -- Complete after sw ack.
+ host_switch(f, HOST_COMPLETE)
+ elseif signal_in(f, SIG_DATA_WRITE) or host_read_completed(f) then
+ -- Complete after all data read or new data written
+ -- remain active
+ signal_clr(f, SIG_RELEASE)
+ host_switch(f, HOST_COMPLETE)
+ end
+ elseif smbus.state(f, HOST_FAIL) then
+ if signal_in(f, SIG_TIMEOUT_ACK) then
+ host_switch(f, HOST_COMPLETE)
+ end
+ end
+
+ if signal_in(f, SIG_START) and not smbus.state(f, HOST_STARTED) then
+ printk(f, f.host.action, "Starting from illegal state\n");
+ end
+
+ signal_clr(f, SIG_DONE)
+ signal_clr(f, SIG_START)
+ signal_clr(f, SIG_DATA_WRITE)
+end
+
+
+
+-- *******************************
+
+-- Mutual exclusion.
+function smbus.get_resource(f)
+ signal_set(f, SIG_INUSE)
+ host_sync(f)
+end
+
+function smbus.put_resource(f)
+ signal_set(f, SIG_RELEASE)
+ host_sync(f)
+end
+
+-- status
+function smbus.state(f, state)
+ return f.host.state.current == state
+end
+
+function smbus.passive(f)
+ return f.host.passive
+end
+
+-- control
+function smbus.start(f, proto)
+ signal_set(f, SIG_START)
+ f.host.start_proto = proto
+ host_sync(f)
+end
+
+function smbus.timeout(f)
+ signal_set(f, SIG_TIMEOUT)
+ host_sync(f)
+end
+
+function smbus.timeout_ack(f)
+ signal_set(f, SIG_TIMEOUT_ACK)
+ host_sync(f)
+end
+
+function smbus.done(f)
+ signal_set(f, SIG_DONE)
+ host_sync(f)
+end
+
+function smbus.ack(f)
+ signal_set(f, SIG_ACK)
+ host_sync(f)
+end
+
+function smbus.abort(f)
+ signal_set(f, SIG_ABORT)
+ host_sync(f)
+end
+
+-- A data read may complete and close an active transaction.
+function smbus.data_read(f, action)
+ if not action.write then
+ signal_clr(f, SIG_DATA_WRITE)
+ host_sync(f)
+ end
+end
+
+-- A data write will close active transaction.
+function smbus.data_write(f, action)
+ if action.write then
+ signal_set(f, SIG_DATA_WRITE)
+ host_sync(f)
+ end
+end
+
+
+
+function smbus.update_register(f, action, smb_reg)
+
+ local data_write = action.write or smbus.passive(f)
+
+ -- A write to data registers completes previous transaction.
+ smbus.data_write(f, action)
+
+ if smb_reg == SMB_REG_SLAVE then
+ if data_write then
+ f.host.slave = action.data
+ else
+ action.data = f.host.slave
+ end
+
+ elseif smb_reg == SMB_REG_CMD then
+ if data_write then
+ f.host.cmd = action.data
+ else
+ action.data = f.host.cmd
+ end
+
+ elseif smb_reg == SMB_REG_DATA0 then
+ if data_write then
+ f.host.data0 = action.data
+ else
+ action.data = f.host.data0
+ end
+ f.host.data0_valid = true
+
+ elseif smb_reg == SMB_REG_DATA1 then
+ if data_write then
+ f.host.data1 = action.data
+ else
+ action.data = f.host.data1
+ end
+ f.host.data1_valid = true
+
+ elseif smb_reg == SMB_REG_BLOCK then
+ if data_write then
+ f.host.block_register = action.data
+ else
+ action.data = f.host.block_register
+ end
+ -- Nothing here, smbus.host_block_data updates datas.
+ -- This exist to check completion below for blocks.
+ elseif smb_reg == SMB_REG_PROTO then
+ -- Nothing here. Protocol updates when signalling start.
+ else
+ printk(f, f.host.action, "Undefined host register\n")
+ end
+
+ -- New read data may complete a waiting transaction.
+ smbus.data_read(f, action)
+end
+
+function smbus.block_data(f, action, index)
+
+ if smbus.passive(f) then
+ if not action.write then
+ f.host.block[index].hw = action.data
+ f.host.block[index].hw_valid = true
+ end
+ f.host.block[index].tmp = action.data
+ f.host.block[index].tmp_valid = true
+ else
+ if action.write then
+ f.host.block[index].tmp = action.data
+ f.host.block[index].tmp_valid = true
+ else
+ action.data = 0xff
+ if f.host.block[index].tmp_valid then
+ action.data = f.host.block[index].tmp
+ elseif f.host.block[index].hw_valid then
+ action.data = f.host.block[index].hw
+ end
+ end
+ end
+
+ -- Detect for block read completion via maximum indexed item.
+ if not action.write then
+ f.host.max_index = math.max(f.host.max_index, index+1)
+ end
+end
+
+local init_action = {
+ name = "init",
+ cs = 0,
+ eip = 0,
+ my_id = 0,
+ parent_id = 0,
+}
+function smbus.init(f)
+ if not f.host then
+ f.host = smbus.host
+ f.host.action = init_action
+ end
+ host_switch(f, HOST_IDLE)
+end
+
+
1
0
New patch to review for serialice: 64f437a Add PCI bridge device filters
by Kyösti Mälkki Oct. 28, 2012
by Kyösti Mälkki Oct. 28, 2012
Oct. 28, 2012
Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1650
-gerrit
commit 64f437a78f1e65de6ba183516c869320f741c567
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Sun Oct 28 10:29:10 2012 +0200
Add PCI bridge device filters
Samples of decoding BARs as found on ich4, ihc7, i945 and i946
bridge devices. See board samples how to enable decoding.
Change-Id: I5b602ca51ac53cd6d61abed63450293fca2192f7
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
SerialICE/simba/i82801.lua | 159 +++++++++++++++++++++++++++++++++++++++++
SerialICE/simba/intel_bars.lua | 69 ++++++++++++++++++
SerialICE/simba/via_bars.lua | 30 ++++++++
3 files changed, 258 insertions(+)
diff --git a/SerialICE/simba/i82801.lua b/SerialICE/simba/i82801.lua
new file mode 100644
index 0000000..f06088d
--- /dev/null
+++ b/SerialICE/simba/i82801.lua
@@ -0,0 +1,159 @@
+-- **********************************************************
+--
+-- SMBus controller handling
+
+
+dofile("intel_smbus.lua")
+
+function smbus_bar_hook(f, action)
+ intel_smbus_setup(action.data, 0x20)
+end
+
+dev_sb_lpc = {
+ pci_dev = pci_bdf(0x0,0x1f,0x3,0x0),
+ name = "Smbus",
+ bar = {},
+}
+
+function enable_smbus_host_bar()
+ pci_cfg16_hook(dev_sb_lpc, 0x20, "SMBus", smbus_bar_hook)
+end
+
+
+-- **********************************************************
+--
+
+dev_power = {
+ pci_dev = pci_bdf(0x0,0x1f,0x0,0x0),
+ name = "SYS",
+ bar = {},
+ acpi = { f = nil },
+ tco = { f = nil },
+}
+
+function pm_io_bar(f, action)
+ f.dev.acpi.name = "ACPI"
+ f.dev.acpi.val = action.data
+ f.dev.acpi.size = 0x60
+ generic_io_bar(f.dev.acpi)
+
+ f.dev.tco.name = "TCO"
+ f.dev.tco.val = action.data + 0x60
+ f.dev.tco.size = 0x20
+ generic_io_bar(f.dev.tco)
+end
+
+function lpc_io_bar(f, action)
+ local base = bit32.band(action.data, 0xffff)
+ local mask = bit32.bor(bit32.rshift(action.data, 16), 3)
+ local size = mask + 1
+
+ base = bit32.band(base, bit32.bnot(mask))
+
+ add_bar(f.dev, f.reg, "LPC", size)
+ f.dev.bar[f.reg].val = base
+ generic_io_bar(f.dev.bar[f.reg])
+end
+
+function lpc_protect_serial_port(f, action)
+ drop_action(f, action, 0)
+end
+
+-- **********************************************************
+--
+-- AC '97 controller handling
+
+
+dev_audio = {
+ pci_dev = pci_bdf(0x0,0x1f,0x5,0x0),
+ name = "Audio",
+ bar = {}
+}
+
+function enable_audio_bars()
+ add_io_bar(dev_audio, 0x10, "NAMBAR", 0x100)
+ add_io_bar(dev_audio, 0x14, "NABMBAR", 0x40)
+ add_mem_bar(dev_audio, 0x18, "MMBAR", 0x200)
+ add_mem_bar(dev_audio, 0x1C, "MBBAR", 0x100)
+end
+
+dev_modem = {
+ pci_dev = pci_bdf(0x0,0x1f,0x6,0x0),
+ name = "Modem",
+ bar = {}
+}
+
+function enable_modem_bars()
+ add_io_bar(dev_modem, 0x10, "MMBAR", 0x100)
+ add_io_bar(dev_modem, 0x14, "MBAR", 0x80)
+end
+
+
+-- **********************************************************
+--
+-- i82801dx
+
+function enable_dx_power_bars()
+ pci_cfg16_hook(dev_power, 0x40, "PM", pm_io_bar)
+ add_io_bar(dev_power, 0x58, "GPIO", 0x40)
+end
+
+function enable_dx_lpc_bars()
+ pci_cfg8_hook(dev_power, 0xe0, "LPC", lpc_protect_serial_port)
+ pci_cfg8_hook(dev_power, 0xe6, "LPC", lpc_protect_serial_port)
+
+ add_io_bar(dev_power, 0xe4, "LPC1", 0x80)
+ add_io_bar(dev_power, 0xec, "LPC2", 0x10)
+end
+
+function enable_hook_i82801dx()
+ enable_smbus_host_bar()
+ enable_dx_power_bars()
+ enable_dx_lpc_bars()
+ enable_audio_bars()
+ enable_modem_bars()
+end
+
+-- **********************************************************
+--
+-- i82801gx
+
+-- ICH7 TPM
+-- Phoenix "Secure" Core bails out if we don't pass the read on ;-)
+filter_ich7_tpm = {
+ id = -1,
+ name = "ICH7 TPM",
+ pre = mem_target_only,
+ post = mem_base_post,
+ base = 0xfed40000,
+ size = 0x00001000,
+ hide = true
+}
+
+function enable_gx_power_bars()
+ pci_cfg16_hook(dev_power, 0x40, "PM", pm_io_bar)
+ add_io_bar(dev_power, 0x48, "GPIO", 0x40)
+end
+
+function enable_gx_lpc_bars()
+ pci_cfg8_hook(dev_power, 0x80, "LPC", lpc_protect_serial_port)
+ pci_cfg16_hook(dev_power, 0x82, "LPC", lpc_protect_serial_port)
+
+ pci_cfg32_hook(dev_power, 0x84, "LPC", lpc_io_bar)
+ pci_cfg32_hook(dev_power, 0x88, "LPC", lpc_io_bar)
+ pci_cfg32_hook(dev_power, 0x8c, "LPC", lpc_io_bar)
+ pci_cfg32_hook(dev_power, 0x90, "LPC", lpc_io_bar)
+end
+
+function enable_hook_i82801gx()
+ enable_hook(mem_hooks, filter_ich7_tpm)
+ add_mem_bar(dev_power, 0xf0, "RCBA", 0x4000)
+ enable_smbus_host_bar()
+ enable_gx_power_bars()
+ enable_gx_lpc_bars()
+ enable_audio_bars()
+ enable_modem_bars()
+end
+
+
+
diff --git a/SerialICE/simba/intel_bars.lua b/SerialICE/simba/intel_bars.lua
new file mode 100644
index 0000000..15607fd
--- /dev/null
+++ b/SerialICE/simba/intel_bars.lua
@@ -0,0 +1,69 @@
+
+-- **********************************************************
+-- Intel e7505
+
+dev_e7505_mch = {
+ pci_dev = pci_bdf(0x0,0x0,0x0,0x0),
+ name = "MCH",
+ bar = {}
+}
+
+function northbridge_e7505()
+ add_mem_bar(dev_e7505_mch, 0x14, "RCOMP", 0x1000)
+end
+
+-- **********************************************************
+-- Intel 82945 PCIe BAR
+
+function i945_pcie_bar(f, action)
+ local base = action.data
+ local sizebits = bit32.band(bit32.rshift(base, 1), 0x3)
+ local baseaddr = 0
+ local size = 0
+
+ if sizebits == 0 then
+ size = 256*1024*1024
+ baseaddr = bit32.band(base, 0xf0000000)
+ elseif sizebits == 1 then
+ size = 128*1024*1024
+ baseaddr = bit32.band(base, 0xf8000000)
+ elseif sizebits == 2 then
+ size = 64*1024*1024
+ baseaddr = bit32.band(base, 0xfc000000)
+ else
+ -- undefined, really
+ baseaddr = bit32.band(base, 0xfe000000)
+ size = 32*1024*1024
+ end
+
+ if bit32.band(base, 1) ~= 0 then
+ pcie_mm_enable(f.dev, f.reg, baseaddr, size)
+ else
+ pcie_mm_disable(f.dev, f.reg, baseaddr, size)
+ end
+end
+
+dev_i945 = {
+ pci_dev = pci_bdf(0,0,0,0),
+ name = "i945",
+ bar = {},
+}
+
+function northbridge_i945()
+ add_mem_bar(dev_i945, 0x40, "EPBAR", 4*1024)
+ add_mem_bar(dev_i945, 0x44, "MCHBAR", 16*1024)
+ add_mem_bar(dev_i945, 0x4c, "DMIBAR", 4*1024)
+ add_mem_bar(dev_i945, 0x60, "(unknown)", 4*1024)
+
+ pci_cfg32_hook(dev_i945, 0x48, "PCI", i945_pcie_bar)
+end
+
+function northbridge_i946()
+ add_mem_bar(dev_i945, 0x40, "PXPEPBAR", 4*1024)
+ add_mem_bar(dev_i945, 0x48, "MCHBAR", 16*1024)
+ add_mem_bar(dev_i945, 0x68, "DMIBAR", 4*1024)
+
+ pci_cfg32_hook(dev_i945, 0x60, "PCI", i945_pcie_bar)
+end
+
+
diff --git a/SerialICE/simba/via_bars.lua b/SerialICE/simba/via_bars.lua
new file mode 100644
index 0000000..7868535
--- /dev/null
+++ b/SerialICE/simba/via_bars.lua
@@ -0,0 +1,30 @@
+
+function sb_pcie_bar(dev, reg, base)
+ local baseaddr = bit32.lshift(base, 16)
+ local size = 64*1024
+
+ pcie_mm_cfg_bar(baseaddr, size)
+end
+
+dev_sb = {
+ pci_dev = pci_bdf(0,0x11,0,0),
+ name = "sb",
+ bar = {},
+}
+
+function nb_pcie_bar(dev, reg, base)
+ local size = 64*1024
+
+ pcie_mm_cfg_bar(base, size)
+end
+
+dev_nb = {
+ pci_dev = pci_bdf(0,0,0,0),
+ name = "nb",
+ bar = {},
+}
+
+function northbridge_vx900()
+ pci_cfg16_hook(dev_sb, 0xbd, "SB_PCI", sb_pcie_bar)
+ pci_cfg32_hook(dev_nb, 0x0, "NB_PCI", nb_pcie_bar)
+end
1
0
New patch to review for serialice: d1e3d39 Add PCI config register filters
by Kyösti Mälkki Oct. 28, 2012
by Kyösti Mälkki Oct. 28, 2012
Oct. 28, 2012
Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1645
-gerrit
commit d1e3d39e9d63adbf51f897e198775f02a8875af8
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Sun Oct 28 11:02:01 2012 +0200
Add PCI config register filters
Config register decoding is enabled by default for IO 0xcf8-0xcff
access only. To enable decode of MMIO style access, it is necessary
to add chipset-specific hook to set base of PCI MMIO config space.
At the moment modifying transactions is limited to conditionally
dropping a write before it reaches target.
Change-Id: Ib4241701dcbd5d617749f1223141171eb8093000
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
SerialICE/simba/pci_cfg.lua | 329 ++++++++++++++++++++++++++++++++++++++++++
SerialICE/simba/serialice.lua | 4 +
2 files changed, 333 insertions(+)
diff --git a/SerialICE/simba/pci_cfg.lua b/SerialICE/simba/pci_cfg.lua
new file mode 100644
index 0000000..88ea266
--- /dev/null
+++ b/SerialICE/simba/pci_cfg.lua
@@ -0,0 +1,329 @@
+
+-- **********************************************************
+--
+-- PCI IO config access
+
+pci_cfg_action = {}
+
+PCI_CFG_READ = false
+PCI_CFG_WRITE = true
+
+pci_cfg_hooks = new_list()
+
+function add_pci_cfg_hook(dev, reg, size, func)
+ local bdfr = bit32.bor(dev.pci_dev, reg)
+ local name = string.format("PCI %x:%02x.%x [%04x]",
+ bit32.band(0xff,bit32.rshift(bdfr, 20)), bit32.band(0x1f,bit32.rshift(bdfr, 15)),
+ bit32.band(0x7,bit32.rshift(bdfr, 12)), bit32.band(0xfff,bdfr))
+ local filter = {
+ id = -1,
+ base = bdfr,
+ dev = dev,
+ reg = reg,
+ size = size,
+ pre = func,
+ name = name,
+ enable = true
+ }
+ enable_hook(pci_cfg_hooks, filter)
+end
+
+function is_pci_cfg_hooked(bdf)
+ local l = pci_cfg_hooks.list
+ while l do
+ if bdf == bit32.band(l.hook.base, bit32.bnot(0x03)) then
+ return true
+ end
+ l = l.next
+ end
+ return false
+end
+
+function walk_pci_pre_hooks(list, action)
+ if list == nil or list.list == nil then
+ return false
+ end
+ local l = list.list
+ local f = nil
+
+ while l do
+ f = l.hook
+ if action.addr == f.base and action.size == f.size then
+ if f.enable and f.pre then
+ f.pre(f, action)
+ end
+ end
+ l = l.next
+ end
+end
+
+function call_pci_cfg_hook(action, bdf, size, data)
+
+ if action.stage == PRE_HOOK then
+ if action.write then
+ pre_action(pci_cfg_action, PCI_CFG_WRITE, bdf, size, data)
+ else
+ --pre_action(pci_cfg_action, PCI_CFG_READ, bdf, size, 0)
+ end
+ walk_pci_pre_hooks(pci_cfg_hooks, pci_cfg_action)
+
+ if pci_cfg_action.dropped then
+ action.dropped = true
+ end
+ elseif action.stage == POST_HOOK then
+
+ end
+end
+
+function pci_cfg8_hook(dev, reg, name, hook)
+ add_bar(dev, reg, name, 0)
+ add_pci_cfg_hook(dev, reg, 1, hook)
+end
+
+function pci_cfg16_hook(dev, reg, name, hook)
+ add_bar(dev, reg, name, 0)
+ add_pci_cfg_hook(dev, reg, 2, hook)
+end
+
+function pci_cfg32_hook(dev, reg, name, hook)
+ add_bar(dev, reg, name, 0)
+ add_pci_cfg_hook(dev, reg, 4, hook)
+end
+
+function io_bar_hook(f, action)
+ f.dev.bar[f.reg].val = action.data
+ generic_io_bar(f.dev.bar[f.reg])
+end
+
+function mem_bar_hook(f, action)
+ f.dev.bar[f.reg].val = action.data
+ generic_mmio_bar(f.dev.bar[f.reg])
+end
+
+function add_bar(dev, reg, name, size)
+ if not dev.bar then
+ dev.bar = {}
+ end
+ if not dev.bar[reg] then
+ dev.bar[reg] = {}
+ dev.bar[reg].f = nil
+ end
+ dev.bar[reg].name = name
+ dev.bar[reg].val = 0x0
+ dev.bar[reg].size = size
+end
+
+function add_io_bar(dev, reg, name, size)
+ add_bar(dev, reg, name, size)
+ add_pci_cfg_hook(dev, reg, 2, io_bar_hook)
+end
+
+function add_mem_bar(dev, reg, name, size)
+ add_bar(dev, reg, name, size)
+ add_pci_cfg_hook(dev, reg, 4, mem_bar_hook)
+end
+
+function pci_bdf(bus, dev, func, reg)
+ return bus*1048576 + dev*32768 + func*4096 + reg
+end
+
+-- Catch partial PCI configuration register writes.
+-- This synthesizes 32/16 bit wide access from separate
+-- 16/8 bit accesses for pci_cfg_hooks.
+
+bv = {}
+
+function pci_cfg_select(f, bdfr)
+ f.reg.bdfr = bdfr
+
+ if f.reg.bdfr_hook ~= bdfr then
+ f.reg.bdfr_hook = 0
+ if (is_pci_cfg_hooked(bdfr)) then
+ f.reg.bdfr_hook = bdfr
+ end
+ for i = 0, 3, 1 do bv[i] = false end
+ end
+end
+
+function pci_cfg_print(f, action, bdfr)
+ local dir_str = "=>"
+ if (action.write) then
+ dir_str = "<="
+ end
+
+ printk(f, action, "%x:%02x.%x [%02x] %s %s\n",
+ bit32.band(0xff,bit32.rshift(bdfr, 20)), bit32.band(0x1f,bit32.rshift(bdfr, 15)),
+ bit32.band(0x7,bit32.rshift(bdfr, 12)), bit32.band(0xfff,bdfr),
+ dir_str, size_data(action.size, action.data))
+end
+
+function pci_cfg_access(f, action)
+
+ if f.reg.bdfr_hook == 0 then
+ return false
+ end
+
+ if not action.write then
+ return false
+ end
+
+ local bdfr = f.reg.bdfr_hook
+ local addr = action.addr
+ local size = action.size
+ local data = action.data
+
+ if not f.reg.reset and ((f.reg.prev_addr ~= addr) or (f.reg.prev_size ~= size)) then
+ new_parent_action()
+ end
+ f.reg.reset = false
+ f.reg.prev_addr = addr
+ f.reg.prev_size = size
+
+ local av = {}
+
+ for i = 0, 3, 1 do av[i] = false end
+
+ ll = 8 * (addr%4)
+ if (size == 1) then
+ av[addr%4] = true
+ bv[addr%4] = true
+ amask = bit32.lshift(0xff, ll)
+ omask = bit32.lshift(data, ll)
+ f.reg.data = bit32.band(f.reg.data, bit32.bnot(amask))
+ f.reg.data = bit32.bor(f.reg.data, omask)
+ elseif (size == 2) then
+ av[addr%4] = true
+ bv[addr%4] = true
+ av[addr%4+1] = true
+ bv[addr%4+1] = true
+ amask = bit32.lshift(0xffff, ll)
+ omask = bit32.lshift(data, ll)
+ f.reg.data = bit32.band(f.reg.data, bit32.bnot(amask))
+ f.reg.data = bit32.bor(f.reg.data, omask)
+ elseif (size == 4) then
+ f.reg.data = data
+ for i = 0, 3, 1 do av[i] = true end
+ for i = 0, 3, 1 do bv[i] = true end
+ end
+
+ local val = 0
+ val = f.reg.data
+ for i = 0, 3, 1 do
+ if (bv[i] and av[i]) then
+ call_pci_cfg_hook(action, bdfr + i, 1, val)
+ end
+ val = bit32.rshift(val, 8)
+ end
+ val = f.reg.data
+ for i = 0, 2, 1 do
+ if ((bv[i] and bv[i+1]) and (av[i] or av[i+1])) then
+ call_pci_cfg_hook(action, bdfr + i, 2, val)
+ end
+ val = bit32.rshift(val, 8)
+ end
+ val = f.reg.data
+ if (bv[0] and bv[1] and bv[2] and bv[3]) then
+ call_pci_cfg_hook(action, bdfr, 4, val)
+ end
+end
+
+-- **********************************************************
+--
+-- PCI IO config access
+
+function pci_io_cfg_pre(f, action)
+ if action.addr == 0xcf8 and action.size == 4 then
+ if action.write then
+ if bit32.band(0x80000000, action.data) ~= 0 then
+ f.reg.reset = true
+ new_parent_action()
+ end
+ local bdfr = 0
+ bdfr = bit32.lshift(action.data, 4)
+ bdfr = bit32.band(bdfr, 0xfffff000)
+ bdfr = bit32.bor(bdfr, bit32.band(action.data, 0xfc))
+ pci_cfg_select(f, bdfr)
+ end
+ return handle_action(f, action)
+ end
+ if action.addr >= 0xcfc and action.addr <= 0xcff then
+ pci_cfg_access(f, action)
+ return handle_action(f, action)
+ end
+ return skip_filter(f, action)
+end
+
+function pci_io_cfg_post(f, action)
+ if action.addr == 0xcf8 and action.size == 4 then
+ return true
+ end
+ if action.addr >= 0xcfc and action.addr <= 0xcff then
+ local byte_offset = action.addr - 0xcfc
+ pci_cfg_print(f, action, f.reg.bdfr + byte_offset)
+ return true
+ end
+ return false
+end
+
+filter_pci_io_cfg = {
+ id = -1,
+ name = "PCI",
+ pre = pci_io_cfg_pre,
+ post = pci_io_cfg_post,
+ hide = hide_pci_io_cfg,
+ base = 0xcf8,
+ size = 0x08,
+ reg = { bdfr = 0, bdfr_hook = 0, data = 0,
+ reset = true, prev_addr = 0, prev_size = 0 }
+}
+
+-- **********************************************************
+--
+-- PCIe MM config access
+
+function pci_mm_cfg_pre(f, action)
+ local bdfr = 0
+ bdfr = bit32.band(action.addr, bit32.bnot(f.base))
+ bdfr = bit32.band(bdfr, bit32.bnot(0x3))
+
+ pci_cfg_select(f, bdfr)
+ pci_cfg_access(f, action)
+
+ return handle_action(f, action)
+end
+
+function pci_mm_cfg_post(f, action)
+ local bdfr = bit32.band(action.addr, bit32.bnot(f.base))
+ pci_cfg_print(f, action, bdfr)
+ return true
+end
+
+filter_pci_mm_cfg = {
+ id = -1,
+ pre = pci_mm_cfg_pre,
+ post = pci_mm_cfg_post,
+ hide = hide_pci_mm_cfg,
+ reg = { bdfr = 0, bdfr_hook = 0, data = 0,
+ reset = true, prev_addr = 0, prev_size = 0 }
+}
+
+function pcie_mm_enable(dev, reg, base, size)
+ local bar = dev.bar[reg]
+ bar.val = base
+ bar.size = size
+
+ if not bar.f then
+ bar.f = filter_pci_mm_cfg
+ end
+
+ bar.f.name = bar.name
+ bar.f.base = bar.val
+ bar.f.size = bar.size
+ enable_hook(mem_hooks, bar.f)
+end
+
+function pcie_mm_disable(dev, reg, base, size)
+ if dev.bar and dev.bar[reg] and dev.bar[reg].f then
+ disable_hook(mem_hooks, dev.bar[reg].f)
+ end
+end
diff --git a/SerialICE/simba/serialice.lua b/SerialICE/simba/serialice.lua
index c179f8c..5529068 100644
--- a/SerialICE/simba/serialice.lua
+++ b/SerialICE/simba/serialice.lua
@@ -27,6 +27,8 @@ io.write("SerialICE: Starting LUA script\n")
-- Set to "false" to show undecoded access for the specified class
hide_rom_access = true
+hide_pci_io_cfg = true
+hide_pci_mm_cfg = true
-- Set to "true" to log every memory and IO access
log_everything = false
@@ -46,6 +48,7 @@ dofile("hooks.lua")
dofile("core_io.lua")
dofile("memory.lua")
dofile("cpu.lua")
+dofile("pci_cfg.lua")
function do_minimal_setup()
enable_hook(io_hooks, filter_io_fallback)
@@ -58,6 +61,7 @@ end
function do_default_setup()
enable_ram()
+ enable_hook(io_hooks, filter_pci_io_cfg)
end
do_minimal_setup()
1
0
New patch to review for serialice: dfdca16 Add legacy PC80 devices in IO space
by Kyösti Mälkki Oct. 28, 2012
by Kyösti Mälkki Oct. 28, 2012
Oct. 28, 2012
Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1646
-gerrit
commit dfdca1655cd73597ed71cbb21b9b04e33798934f
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Sun Oct 28 11:13:35 2012 +0200
Add legacy PC80 devices in IO space
These devices appear at fixed IO addresses and are mostly implemented
in the southbridge chip.
Change-Id: I4a20058e0cbc31f1b5777fe99966c0499909a553
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
SerialICE/simba/pc80.lua | 546 ++++++++++++++++++++++++++++++++++++++++++
SerialICE/simba/serialice.lua | 11 +
2 files changed, 557 insertions(+)
diff --git a/SerialICE/simba/pc80.lua b/SerialICE/simba/pc80.lua
new file mode 100644
index 0000000..7ce439c
--- /dev/null
+++ b/SerialICE/simba/pc80.lua
@@ -0,0 +1,546 @@
+-- **********************************************************
+--
+-- Debug POST port at IO 0x80
+
+function debugport_post(f, action)
+ if action.write then
+ printk(f, action, "*** %02x ***\n", action.data)
+ return true
+ end
+ return false
+end
+
+filter_debugport = {
+ id = -1,
+ name = "POST",
+ pre = handle_action,
+ post = debugport_post,
+ hide = true,
+ base = 0x80,
+ size = 0x1
+}
+
+
+-- **********************************************************
+--
+-- i8259 PIC
+
+function i8259_pre(f, action)
+ local master = (bit32.rshift(0x05, action.addr) == 0x1)
+ local slave = (bit32.rshift(0x05, action.addr) == 0x5)
+ local reg = bit32.band(0x03, action.addr)
+ if reg == 0 or reg == 1 then
+ return handle_action(f, action)
+ end
+ return skip_filter(f, action)
+end
+
+function i8259_post(f,action)
+ local reg = bit32.band(0x03, action.addr)
+ if reg == 0 or reg == 1 then
+ return true
+ end
+ return false
+end
+
+function i8259_edge_pre(f, action)
+ return handle_action(f, action)
+end
+
+function i8259_edge_post(f,action)
+ return true
+end
+
+filter_i8259_master = {
+ id = -1,
+ name = "i8259 A",
+ pre = i8259_pre,
+ post = i8259_post,
+ hide = hide_i8259_io,
+ base = 0x20,
+ size = 0x20
+}
+
+filter_i8259_slave = {
+ id = -1,
+ name = "i8259 B",
+ pre = i8259_pre,
+ post = i8259_post,
+ hide = hide_i8259_io,
+ base = 0xa0,
+ size = 0x20
+}
+
+filter_i8259_edge = {
+ id = -1,
+ name = "i8259 C",
+ pre = i8259_edge_pre,
+ post = i8259_edge_post,
+ hide = hide_i8259_io,
+ base = 0x4d0,
+ size = 0x2
+}
+
+-- **********************************************************
+--
+-- i8237 DMA
+
+function i8237_pre(f, action)
+ if action.addr == 0x80 then
+ return skip_filter(f, action)
+ end
+ return handle_action(f, action)
+end
+
+function i8237_post(f, action)
+ if action.addr == 0x80 then
+ return false
+ end
+ return true
+end
+
+
+filter_i8237_a = {
+ id = -1,
+ name = "i8237 A",
+ pre = i8237_pre,
+ post = i8237_post,
+ hide = hide_i8237_io,
+ base = 0x00,
+ size = 0x20
+}
+filter_i8237_b = {
+ id = -1,
+ name = "i8237 B",
+ pre = i8237_pre,
+ post = i8237_post,
+ hide = hide_i8237_io,
+ base = 0x80,
+ size = 0x20
+}
+filter_i8237_c = {
+ id = -1,
+ name = "i8237 C",
+ pre = i8237_pre,
+ post = i8237_post,
+ hide = hide_i8237_io,
+ base = 0xc0,
+ size = 0x20
+}
+
+
+-- **********************************************************
+--
+-- i8254 IRQ0 and Speaker
+
+function i8254_pre(f, action)
+
+ -- nothing to do on reads
+ if not action.write then
+ return handle_action(f, action)
+ end
+
+ local reg = bit32.band(0x03, action.addr)
+ if reg >= 0x0 and reg < 0x03 then
+ local counter_n = 0
+ local counter_p = 0
+ if f.counter[reg].lsb then
+ f.counter[reg].lsb = f.counter[reg].after_lsb
+ counter_n = action.data
+ counter_p = bit32.band(0xff00, f.counter[reg].init)
+ else
+ counter_n = bit32.lshift(action.data, 8)
+ counter_p = bit32.band(0x00ff, f.counter[reg].init)
+ end
+ f.counter[reg].init = bit32.bor(counter_n, counter_p)
+ elseif reg == 0x03 then
+ local reg2 = bit32.rshift(action.data, 6)
+ local rwsel = bit32.band(0x3, bit32.rshift(action.data, 4))
+ if reg2 == 0x3 then
+ if bit32.band(0x10, action.data) == 0 then
+ f.counter[0].readback = (bit32.band(0x2, action.data) ~= 0)
+ f.counter[1].readback = (bit32.band(0x4, action.data) ~= 0)
+ f.counter[2].readback = (bit32.band(0x8, action.data) ~= 0)
+ end
+ if bit32.band(0x20, action.data) == 0 then
+ f.counter[0].latch = (bit32.band(0x2, action.data) ~= 0)
+ f.counter[1].latch = (bit32.band(0x4, action.data) ~= 0)
+ f.counter[2].latch = (bit32.band(0x8, action.data) ~= 0)
+ end
+ elseif rwsel == 0x0 then
+ f.counter[reg2].latch = true
+ else
+ f.counter[reg2].mode = bit32.band(0xf, action.data)
+ if rwsel == 0x1 then
+ f.counter[reg2].lsb = true
+ f.counter[reg2].after_lsb = true
+ elseif rwsel == 0x2 then
+ f.counter[reg2].lsb = false
+ f.counter[reg2].after_lsb = false
+ elseif rwsel == 03 then
+ f.counter[reg2].lsb = true
+ f.counter[reg2].after_lsb = false
+ end
+ end
+ end
+ return handle_action(f, action)
+end
+
+function i8254_post(f, action)
+ local reg = bit32.band(0x03, action.addr)
+ if reg >= 0x0 and reg < 0x03 then
+ if action.write then
+ local mode = bit32.band(0x0f, f.counter[reg].mode);
+ local modestr = "Mode" .. mode
+ if mode == 0x4 then
+ modestr = "Square Wave"
+ elseif mode == 0x6 then
+ modestr = "Rate Generator"
+ end
+ if bit32.band(0x01, mode) ~= 0 then
+ modestr = modestr .. " (BCD)"
+ end
+
+ local period = 838 * f.counter[reg].init
+ if reg == 0 then
+ if period == 0 then
+ printk(f, action, "IRQ0 disabled\n")
+ else
+ printk(f, action, "IRQ0 (%s): %d ns\n", modestr, period)
+ end
+ elseif reg == 1 then
+ if period == 0 then
+ printk(f, action, "Refresh disabled\n")
+ else
+ printk(f, action, "Refresh (%s): %d ns\n", modestr, period)
+ end
+ elseif reg == 2 then
+ if period ~= 0 then
+ local spktone = 1193000 / f.counter[reg].init
+ printk(f, action, "Speaker Tone (%s): %d kHz\n", modestr, spktone)
+ end
+ end
+ else
+ if f.counter[reg].readback then
+ f.counter[reg].readback = false
+ f.counter[reg].status = action.data
+ printk(f, action, "[%d] status = %02x\n", reg, f.counter[reg].status)
+ end
+ if f.counter[reg].latch then
+ f.counter[reg].latch = false
+ f.counter[reg].current = action.data
+ printk(f, action, "[%d] current = %d\n", reg, f.counter[reg].current)
+ end
+ end
+ elseif reg == 0x03 then
+ end
+ return true
+end
+
+i8254_counters = {}
+i8254_counters[0x0] = { init=0, current=0, latch, readback, status=0 }
+i8254_counters[0x1] = { init=0, current=0, latch, readback, status=0 }
+i8254_counters[0x2] = { init=0, current=0, latch, readback, status=0 }
+
+filter_i8254_a = {
+ id = -1,
+ name = "i8254 A",
+ pre = i8254_pre,
+ post = i8254_post,
+ base = 0x40,
+ hide = hide_i8254_io,
+ size = 4,
+ counter = i8254_counters,
+}
+filter_i8254_b = {
+ id = -1,
+ name = "i8254 B",
+ pre = i8254_pre,
+ post = i8254_post,
+ base = 0x50,
+ hide = hide_i8254_io,
+ size = 4,
+ counter = i8254_counters,
+}
+
+
+-- **********************************************************
+--
+-- i8042 KBD, A20, Reset(?)
+
+function i8042_write(f, action)
+ if action.addr == 0x60 then
+ f.reg.data = action.data
+ f.reg.sts = bit32.band(f.reg.sts, 0xf7)
+ if (f.reg.cmd == 0xd1) then
+ f.reg.A20 = (bit32.band(0x02, action.data) == 0x02)
+ end
+ return handle_action(f, action)
+ end
+ if action.addr == 0x64 then
+ f.reg.cmd = action.data
+ f.reg.sts = bit32.bor(f.reg.sts, 0x0a)
+ return handle_action(f, action)
+ end
+ return skip_filter(f, action)
+end
+
+function i8042_read(f, action)
+ if action.addr == 0x60 then
+ f.reg.sts = bit32.band(f.reg.sts, 0xfe)
+ return handle_action(f, action)
+ end
+ if action.addr == 0x64 then
+ return handle_action(f, action)
+ end
+ return skip_filter(f, action)
+end
+
+function i8042_pre(f, action)
+ if (action.write) then
+ return i8042_write(f, action)
+ else
+ return i8042_read(f, action)
+ end
+end
+
+function i8042_post(f, action)
+ if action.addr == 0x60 then
+ if action.write and f.reg.cmd == 0xd1 then
+ if f.reg.A20 then
+ printk(f, action, "A20 enabled\n")
+ else
+ printk(f, action, "A20 disabled\n")
+ end
+ end
+ return true
+ end
+ if action.addr == 0x64 then
+ return true
+ end
+ return false
+end
+
+filter_i8042 = {
+ id = -1,
+ name = "i8042",
+ pre = i8042_pre,
+ post = i8042_post,
+ hide = hide_i8042_io,
+ base = 0x60,
+ size = 0x5,
+ reg = { data = 0, sts = 0, cmd = 0, A20 = 0 }
+}
+
+
+-- **********************************************************
+--
+-- CMOS nvram
+
+
+function nvram_bank(addr)
+ if bit32.band(0xfe, addr) == 0x70 then
+ return 1
+ elseif bit32.band(0xfe, addr) == 0x72 then
+ return 2
+ elseif bit32.band(0xfe, addr) == 0x74 then
+ return 2
+ else
+ return 0
+ end
+end
+
+function nvram_write(f, action)
+ local val = action.data
+ local rtc = false
+ local is_index = (bit32.band(0x01, action.addr) == 0x0)
+ local bank = nvram_bank(action.addr)
+
+ if bank == 1 then
+ if is_index then
+ f.reg.p70 = bit32.band(0x7f, val)
+ if f.reg.p70 < 0x0E then
+ rtc = true
+ end
+ else
+ f.nvram_data[f.reg.p70] = val
+ f.nvram_set[f.reg.p70] = true
+ if f.reg.p70 < 0x0E then
+ rtc = true
+ end
+ end
+ elseif bank == 2 then
+ if is_index then
+ f.reg.p72 = bit32.band(0x7f, val)
+ else
+ local index = 0x80 + f.reg.p72
+ f.nvram_data[index] = val
+ f.nvram_set[index] = true
+ end
+ end
+ if cache_nvram and not rtc then
+ return fake_action(f, action, val)
+ else
+ return handle_action(f, action)
+ end
+end
+
+function nvram_read(f, action)
+ local val = 0
+ local rtc = false
+ local is_index = (bit32.band(0x01, action.addr) == 0x0)
+ local bank = nvram_bank(action.addr)
+
+ if bank == 1 then
+ if is_index then
+ -- NMI returned as 0
+ val = f.reg.p70
+ if f.reg.p70 < 0x0E then
+ rtc = true
+ end
+ else
+ if f.reg.p70 < 0x0E then
+ rtc = true
+ elseif f.nvram_set[f.reg.p70] then
+ val = f.nvram_data[f.reg.p70]
+ end
+ end
+ else -- bank
+ if is_index then
+ -- NMI returned as 0
+ val = f.reg.p72
+ else
+ local index = 0x80 + f.reg.p72
+ if f.nvram_set[index] then
+ val = f.nvram_data[index]
+ end
+ end
+ end
+ if cache_nvram and not rtc then
+ return fake_action(f, action, val)
+ else
+ return handle_action(f, action)
+ end
+end
+
+function nvram_pre(f, action)
+ if (action.write) then
+ return nvram_write(f, action)
+ else
+ return nvram_read(f, action)
+ end
+end
+
+function nvram_post(f, action)
+ if bit32.band(0x01, action.addr) == 0x0 then
+ return true
+ end
+
+ local bank = nvram_bank(action.addr)
+ if (action.write) then
+ if bank == 1 then
+ printk(f, action, "[%02x] <= %02x\n", f.reg.p70, action.data)
+ elseif bank == 2 then
+ printk(f, action, "[%02x] <= %02x\n", 0x80 + f.reg.p72, action.data)
+ end
+ else
+ if bank == 1 then
+ printk(f, action, "[%02x] => %02x\n", f.reg.p70, action.data)
+ elseif bank == 2 then
+ printk(f, action, "[%02x] => %02x\n", 0x80 + f.reg.p72, action.data)
+ end
+ end
+ return true
+end
+
+filter_nvram = {
+ id = -1,
+ name = "NVram",
+ pre = nvram_pre,
+ post = nvram_post,
+ base = 0x70,
+ size = 8,
+ hide = hide_nvram_io,
+ reg = { p70 = 0, p72 = 0 },
+ nvram_data = {},
+ nvram_set = {},
+}
+
+
+-- **********************************************************
+--
+-- Reset at 0xcf9
+
+function sys_rst_pre(f, action)
+ if action.size == 1 then
+ if action.write and bit32.band(action.data, 0x04) == 0x04 then
+ SerialICE_system_reset()
+ end
+ return handle_action(f, action)
+ end
+ return skip_filter(f, action)
+end
+
+function sys_rst_post(f, action)
+ if action.size == 1 then
+ if action.write then
+ printk(f, action, "Control = %02x\n", action.data)
+ return true
+ end
+ end
+ return false
+end
+
+filter_reset = {
+ id = -1,
+ name = "Reset",
+ pre = sys_rst_pre,
+ post = sys_rst_post,
+ hide = false,
+ base = 0xcf9,
+ size = 1
+}
+
+-- **********************************************************
+--
+-- VGA io
+
+function vga_io_pre(f, action)
+ return skip_filter(f, action)
+end
+
+function vga_io_post(f, action)
+ return true
+end
+
+filter_vga_io = {
+ id = -1,
+ name = "VGA",
+ pre = vga_io_pre,
+ post = vga_io_post,
+ hide = false,
+ base = 0x3c0,
+ size = 0x20,
+}
+
+
+-- **********************************************************
+--
+-- Enable all PC80 stuff
+
+function enable_hook_pc80()
+ enable_hook(io_hooks, filter_i8237_a)
+ enable_hook(io_hooks, filter_i8237_b)
+ enable_hook(io_hooks, filter_i8237_c)
+ enable_hook(io_hooks, filter_i8259_master)
+ enable_hook(io_hooks, filter_i8259_slave)
+ enable_hook(io_hooks, filter_i8259_edge)
+ enable_hook(io_hooks, filter_i8042)
+ enable_hook(io_hooks, filter_i8254_a)
+ enable_hook(io_hooks, filter_i8254_b)
+ enable_hook(io_hooks, filter_reset)
+ enable_hook(io_hooks, filter_nvram)
+ enable_hook(io_hooks, filter_vga_io)
+ enable_hook(io_hooks, filter_debugport)
+end
+
diff --git a/SerialICE/simba/serialice.lua b/SerialICE/simba/serialice.lua
index 5529068..4b63e25 100644
--- a/SerialICE/simba/serialice.lua
+++ b/SerialICE/simba/serialice.lua
@@ -29,11 +29,20 @@ io.write("SerialICE: Starting LUA script\n")
hide_rom_access = true
hide_pci_io_cfg = true
hide_pci_mm_cfg = true
+hide_nvram_io = true
+hide_i8042_io = false
+hide_i8237_io = true
+hide_i8254_io = true
+hide_i8259_io = true
-- Set to "true" to log every memory and IO access
log_everything = false
+-- Use lua table for NVram
+-- RTC registers 0x0-0xd go to HW
+cache_nvram = false
+
rom_size = 4 * 1024 * 1024
rom_base = 0x100000000 - rom_size
@@ -49,6 +58,7 @@ dofile("core_io.lua")
dofile("memory.lua")
dofile("cpu.lua")
dofile("pci_cfg.lua")
+dofile("pc80.lua")
function do_minimal_setup()
enable_hook(io_hooks, filter_io_fallback)
@@ -62,6 +72,7 @@ end
function do_default_setup()
enable_ram()
enable_hook(io_hooks, filter_pci_io_cfg)
+ enable_hook_pc80()
end
do_minimal_setup()
1
0
Oct. 28, 2012
Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1647
-gerrit
commit eb43380a5a24737214e43f9200630ef96fdbcc79
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Sun Oct 28 11:32:48 2012 +0200
Add superio filtering
Decoder is able to pretty-print the config cycles to port 0x2e/0x4e
and activate new IO regions. One should provide a map of LDN functions
with the size of each IO region as part of the mainboard script.
Change-Id: I976f43818b43a30db97b4e679de04e399f691b97
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
SerialICE/simba/serialice.lua | 11 ++
SerialICE/simba/superio.lua | 259 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 270 insertions(+)
diff --git a/SerialICE/simba/serialice.lua b/SerialICE/simba/serialice.lua
index 4b63e25..3700589 100644
--- a/SerialICE/simba/serialice.lua
+++ b/SerialICE/simba/serialice.lua
@@ -34,6 +34,7 @@ hide_i8042_io = false
hide_i8237_io = true
hide_i8254_io = true
hide_i8259_io = true
+hide_superio_cfg = true
-- Set to "true" to log every memory and IO access
log_everything = false
@@ -43,6 +44,9 @@ log_everything = false
-- RTC registers 0x0-0xd go to HW
cache_nvram = false
+-- SMSC 0x07, Winbond 0x06 ?
+DEFAULT_SUPERIO_LDN_REGISTER = 0x07
+
rom_size = 4 * 1024 * 1024
rom_base = 0x100000000 - rom_size
@@ -59,6 +63,7 @@ dofile("memory.lua")
dofile("cpu.lua")
dofile("pci_cfg.lua")
dofile("pc80.lua")
+dofile("superio.lua")
function do_minimal_setup()
enable_hook(io_hooks, filter_io_fallback)
@@ -73,6 +78,12 @@ function do_default_setup()
enable_ram()
enable_hook(io_hooks, filter_pci_io_cfg)
enable_hook_pc80()
+ enable_hook_superio(0x2e, DEFAULT_SUPERIO_LDN_REGISTER)
+ enable_hook_superio(0x4e, DEFAULT_SUPERIO_LDN_REGISTER)
+ enable_hook(io_hooks, filter_com1)
+ if superio_initialization then
+ superio_initialization()
+ end
end
do_minimal_setup()
diff --git a/SerialICE/simba/superio.lua b/SerialICE/simba/superio.lua
new file mode 100644
index 0000000..1248af5
--- /dev/null
+++ b/SerialICE/simba/superio.lua
@@ -0,0 +1,259 @@
+
+
+function pnp_switch_ldn(f, data)
+ if not f.ldn[data] then
+ f.ldn[data] = { data = {}, set = {}, bar0 = {}, bar1 = {} }
+ end
+ f.pnp.active_ldn = data
+end
+
+function pnp_select_cfg(f, data)
+ f.pnp.reg = data
+end
+
+function pnp_store_cfg(f, data)
+ local reg = f.pnp.reg
+ if reg < 0x30 then
+ f.chip.data[reg] = data;
+ f.chip.set[reg] = true;
+ else
+ local ldn = f.pnp.active_ldn
+ f.ldn[ldn].data[reg] = data;
+ f.ldn[ldn].set[reg] = true;
+ end
+end
+
+
+-- **********************************************************
+--
+-- SuperIO device handling
+
+function superio_pnpdev(f)
+ return string.format("%s %02x:%02x", f.name, f.base, f.pnp.active_ldn)
+end
+
+function superio_dev_post(f, action)
+ if f.pnp.reg < 0x30 then
+ printk(f, action, "%02x: ", f.base)
+ else
+ printk(f, action, "%02x:%02x ", f.base, f.pnp.active_ldn)
+ end
+end
+
+function superio_register_post(f, action)
+ superio_dev_post(f, action)
+ if action.write then
+ printf("[%02x] <= %02x\n", f.pnp.reg, action.data)
+ else
+ printf("[%02x] => %02x\n", f.pnp.reg, action.data)
+ end
+end
+
+function superio_try_enable_io(f, idx)
+
+ local ldn = f.ldn[f.pnp.active_ldn]
+
+ if ldn.set[0x30] and ldn.data[0x30] ~= 0x0 then
+ if idx == 0 and ldn.set[0x60] and ldn.set[0x61] then
+ local iobase = bit32.bor(bit32.lshift(ldn.data[0x60], 8), ldn.data[0x61])
+ if not ldn.bar0.size then
+ ldn.bar0.size = 1
+ end
+ if not ldn.bar0.name then
+ ldn.bar0.name = superio_pnpdev(f)
+ end
+ ldn.bar0.val = iobase
+ generic_io_bar(ldn.bar0)
+ end
+ if idx == 1 and ldn.set[0x62] and ldn.set[0x63] then
+ local iobase = bit32.bor(bit32.lshift(ldn.data[0x62], 8), ldn.data[0x63])
+ if not ldn.bar1.size then
+ ldn.bar1.size = 1
+ end
+ if not ldn.bar1.name then
+ ldn.bar1.name = superio_pnpdev(f)
+ end
+ ldn.bar1.val = iobase
+ generic_io_bar(ldn.bar1)
+ end
+ end
+end
+
+function superio_try_enable_ldn(f, action)
+ local ldn = f.ldn[f.pnp.active_ldn]
+
+ if ldn.set[0x30] and ldn.data[0x30] == 0x0 then
+ superio_dev_post(f, action)
+ printf("disabled\n")
+ else
+ superio_dev_post(f, action)
+ printf("enabled\n")
+ end
+end
+
+function superio_pre(f, action)
+ if not action.write then
+ return handle_action(f, action)
+ end
+
+ if action.addr == f.base then
+ pnp_select_cfg(f, action.data)
+ return handle_action(f, action)
+ end
+
+ if action.addr == f.base + 0x01 then
+ -- Also creates new LDN instance, if necessary.
+ if f.pnp.reg == f.pnp.ldn_register then
+ pnp_switch_ldn(f, action.data)
+ end
+
+ pnp_store_cfg(f, action.data)
+
+ -- Don't allow that our SIO power gets disabled.
+ if f.pnp.reg == 0x02 then
+ return drop_action(f, action, 0)
+ end
+
+ -- Don't mess with oscillator setup.
+ if f.pnp.reg == 0x24 then
+ return drop_action(f, action, 0)
+ end
+ return handle_action(f, action)
+ end
+
+ -- should not reach here
+ return skip_filter(f, action)
+end
+
+function superio_post(f, action)
+
+ -- Do not log change of register or LDN.
+ if action.addr == f.base or f.pnp.reg == f.pnp.ldn_register then
+ return true
+ end
+
+ if not action.write then
+ superio_register_post(f, action)
+ return true
+ end
+
+ local ldn = f.ldn[f.pnp.active_ldn]
+
+ -- Log base address once both bytes are set.
+
+ if ( f.pnp.reg == 0x60 or f.pnp.reg == 0x61 ) then
+ superio_try_enable_io(f, 0)
+ return true
+ end
+
+ if ( f.pnp.reg == 0x62 or f.pnp.reg == 0x63 ) then
+ superio_try_enable_io(f, 1)
+ return true
+ end
+
+ if f.pnp.reg == 0x30 then
+ superio_try_enable_io(f, 0)
+ superio_try_enable_io(f, 1)
+ superio_try_enable_ldn(f, action)
+ return true
+ end
+
+ if f.pnp.reg == 0x70 then
+ superio_dev_post(f, action)
+ printf("irq = %d\n", ldn.data[0x70])
+ return true
+ end
+ if f.pnp.reg == 0x72 then
+ superio_dev_post(f, action)
+ printf("irq2 = %d\n", ldn.data[0x72])
+ return true
+ end
+
+ superio_register_post(f, action)
+ return true
+end
+
+
+filter_superio_2e = {
+ id = -1,
+ name = "PnP",
+ pre = superio_pre,
+ post = superio_post,
+ base = 0x2e,
+ size = 0x02,
+ hide = hide_superio_cfg,
+ chip = { data = {}, set = {} },
+ pnp = { reg = 0, active_ldn = -1, ldn_register = 0 },
+ ldn = {},
+}
+filter_superio_4e = {
+ id = -1,
+ name = "PnP",
+ pre = superio_pre,
+ post = superio_post,
+ base = 0x4e,
+ size = 0x02,
+ hide = hide_superio_cfg,
+ chip = { data = {}, set = {} },
+ pnp = { reg = 0, active_ldn = -1, ldn_register = 0 },
+ ldn = {},
+}
+
+
+function superio_get_filter(cfg_base)
+ if cfg_base == 0x2e then
+ return filter_superio_2e
+ elseif cfg_base == 0x4e then
+ return filter_superio_4e
+ else
+ return nil
+ end
+end
+
+function superio_set_ldn_register(f, ldn_register)
+ f.pnp.ldn_register = ldn_register
+end
+
+function superio_new_ldn(f, idx)
+ if not f.ldn[idx] then
+ f.ldn[idx] = { data = {}, set = {}, bar0 = {}, bar1 = {} }
+ end
+end
+
+function superio_ldn_iobase0(f, idx, name, size)
+ f.ldn[idx].bar0.name = name
+ f.ldn[idx].bar0.size = size
+end
+
+function superio_ldn_iobase1(f, idx, name, size)
+ f.ldn[idx].bar1.name = name
+ f.ldn[idx].bar1.size = size
+end
+
+function enable_hook_superio(base, ldn_register)
+ local sio = superio_get_filter(base)
+ superio_set_ldn_register(sio, ldn_register)
+ enable_hook(io_hooks, sio)
+end
+
+-- **********************************************************
+--
+-- Serial Port handling
+
+function com_pre(f, action)
+ if (action.write) then
+ return drop_action(f, action, action.data)
+ else
+ return drop_action(f, action, 0xff)
+ end
+end
+
+filter_com1 = {
+ id = -1,
+ name = "COM1",
+ pre = com_pre,
+ post = io_post,
+ base = 0x3f8,
+ size = 8,
+ hide = false,
+}
1
0
New patch to review for serialice: 7fb6c48 Add simba, modular filtering
by Kyösti Mälkki Oct. 28, 2012
by Kyösti Mälkki Oct. 28, 2012
Oct. 28, 2012
Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1642
-gerrit
commit 7fb6c48cfb4e9e5d2e948b936b3c499598e55061
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Sun Oct 28 10:41:54 2012 +0200
Add simba, modular filtering
This implement the core interface of IO and memory operations
between Qemu and SerialICE LUA filter scripts.
Change-Id: I116fa45597c321155c7e24bb20e497c3e93640b0
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
SerialICE/simba/core_io.lua | 84 +++++++++++++
SerialICE/simba/cpu.lua | 77 ++++++++++++
SerialICE/simba/hooks.lua | 274 ++++++++++++++++++++++++++++++++++++++++++
SerialICE/simba/interface.lua | 161 +++++++++++++++++++++++++
SerialICE/simba/memory.lua | 198 ++++++++++++++++++++++++++++++
SerialICE/simba/output.lua | 71 +++++++++++
SerialICE/simba/serialice.lua | 69 +++++++++++
7 files changed, 934 insertions(+)
diff --git a/SerialICE/simba/core_io.lua b/SerialICE/simba/core_io.lua
new file mode 100644
index 0000000..38a2df0
--- /dev/null
+++ b/SerialICE/simba/core_io.lua
@@ -0,0 +1,84 @@
+-- **********************************************************
+--
+
+function io_undefined(f, action)
+ action.to_hw = true
+ action.to_qemu = false
+ action.undefined = true
+ return true
+end
+
+function io_post(f, action)
+ if (action.write) then
+ printk(f, action, "out%s %04x <= %s\n", size_suffix(action.size), action.addr, size_data(action.size, action.data))
+ else
+ printk(f, action, " in%s %04x => %s\n", size_suffix(action.size), action.addr, size_data(action.size, action.data))
+ end
+ return true
+end
+
+function io_base_post(f, action)
+ if (action.write) then
+ printk(f, action, "[%04x] <= %s\n", bit32.band(action.addr, (f.size - 1)), size_data(action.size, action.data))
+ else
+ printk(f, action, "[%04x] => %s\n", bit32.band(action.addr, (f.size - 1)), size_data(action.size, action.data))
+ end
+ return true
+end
+
+filter_io_fallback = {
+ id = -1,
+ name = "IO",
+ pre = io_undefined,
+ post = io_post,
+ base = 0x0,
+ size = 0x10000,
+}
+
+-- **********************************************************
+--
+
+function mem_undefined(f, action)
+ if (action.write) then
+ action.to_hw = true
+ action.to_qemu = false
+ else
+ action.to_hw = false
+ action.to_qemu = true
+ end
+ action.undefined = true
+ return true
+end
+
+function mem_post(f, action)
+ if (action.write) then
+ printk(f, action, "write%s %08x <= %s", size_suffix(action.size), action.addr, size_data(action.size, action.data))
+ else
+ printk(f, action, " read%s %08x => %s", size_suffix(action.size), action.addr, size_data(action.size, action.data))
+ end
+ if action.to_hw then
+ printf(" *")
+ end
+ printf("\n")
+ return true
+end
+
+function mem_base_post(f, action)
+ if (action.write) then
+ printk(f, action, "[%08x] <= %s\n", bit32.band(action.addr, (f.size - 1)), size_data(action.size, action.data))
+ else
+ printk(f, action, "[%08x] => %s\n", bit32.band(action.addr, (f.size - 1)), size_data(action.size, action.data))
+ end
+ return true
+end
+
+
+filter_mem_fallback = {
+ id = -1,
+ name = "MEM",
+ pre = mem_undefined,
+ post = mem_post,
+ base = 0x0,
+ size = 0x100000000
+}
+
diff --git a/SerialICE/simba/cpu.lua b/SerialICE/simba/cpu.lua
new file mode 100644
index 0000000..00162ae
--- /dev/null
+++ b/SerialICE/simba/cpu.lua
@@ -0,0 +1,77 @@
+-- **********************************************************
+-- CPU MSR filters
+
+function var_mtrr_post(f, action)
+
+ local addr = action.rin.ecx
+ local hi = action.rin.edx
+ local lo = action.rin.eax
+
+ if addr % 2 == 0 then
+ mt = lo % 0x100
+ if mt == 0 then memtype = "Uncacheable"
+ elseif mt == 1 then memtype = "Write-Combine"
+ elseif mt == 4 then memtype = "Write-Through"
+ elseif mt == 5 then memtype = "Write-Protect"
+ elseif mt == 6 then memtype = "Write-Back"
+ else memtype = "Unknown"
+ end
+ printk(f, action, "Set MTRR %x base to %08x.%08x (%s)\n", (addr - 0x200) / 2, hi, bit32.band(lo, 0xffffff00), memtype)
+ else
+ if bit32.band(lo, 0x800) == 0x800 then
+ valid = "valid"
+ else
+ valid = "disabled"
+ end
+ printk(f, action, "Set MTRR %x mask to %08x.%08x (%s)\n", (addr - 0x200) / 2, hi, bit32.band(lo, 0xfffff000), valid)
+ end
+end
+
+function cpumsr_pre(f, action)
+ return handle_action(f, action)
+end
+
+function cpumsr_post(f, action)
+ if action.write then
+ printk(f, action, "[%08x] <= %08x.%08x\n",
+ action.rin.ecx, action.rin.edx, action.rin.eax)
+ if action.addr >= 0x200 and action.addr < 0x210 then
+ var_mtrr_post(f, action)
+ end
+ else
+ printk(f, action, "[%08x] => %08x.%08x\n",
+ action.rin.ecx, action.rout.edx, action.rout.eax)
+ end
+ return true
+end
+
+
+filter_cpumsr_fallback = {
+ id = -1,
+ name = "CPU MSR",
+ pre = cpumsr_pre,
+ post = cpumsr_post,
+}
+
+
+-- **********************************************************
+-- CPUID filters
+
+function cpuid_pre(f, action)
+ return handle_action(f, action)
+end
+
+function cpuid_post(f, action)
+ printk(f, action, "eax: %08x; ecx: %08x => %08x.%08x.%08x.%08x\n",
+ action.rin.eax, action.rin.ecx,
+ action.rout.eax, action.rout.ebx, action.rout.ecx, action.rout.edx)
+ return true
+end
+
+filter_cpuid_fallback = {
+ id = -1,
+ name = "CPUID",
+ pre = cpuid_pre,
+ post = cpuid_post,
+}
+
diff --git a/SerialICE/simba/hooks.lua b/SerialICE/simba/hooks.lua
new file mode 100644
index 0000000..fa61ab4
--- /dev/null
+++ b/SerialICE/simba/hooks.lua
@@ -0,0 +1,274 @@
+
+
+function new_list()
+ return { list = nil }
+end
+
+next_filter_id = 1
+next_action_id = 1
+current_parent_id = 0
+
+function action_id()
+ local n = next_action_id
+ next_action_id = next_action_id + 1
+ return n
+end
+
+function new_parent_action()
+ current_parent_id = action_id()
+end
+
+
+io_hooks = new_list()
+mem_hooks = new_list()
+
+cpumsr_hooks = new_list()
+cpuid_hooks = new_list()
+
+
+function enable_hook(list, filter)
+ if not filter then
+ printks(froot, "Enable_hook called with filter==nil\n")
+ return
+ end
+
+ local l = list.list
+ local found = false
+ while l and not found do
+ found = (l.hook == filter)
+ l = l.next
+ end
+ if not found then
+ if (filter.id < 0) then
+ filter.id = next_filter_id
+ next_filter_id = next_filter_id + 1
+ end
+ list.list = { next = list.list, hook = filter }
+ end
+ if (list == io_hooks) then
+ printks(fresource, "[%04x] IO [%04x-%04x] = %s\n",
+ filter.id, filter.base, filter.base + filter.size - 1, filter.name)
+ elseif (list == mem_hooks) then
+ printks(fresource, "[%04x] MEM [%08x-%08x] = %s\n",
+ filter.id, filter.base, filter.base + filter.size - 1, filter.name)
+ else
+ printks(fresource, "[%04x] %s\n", filter.id, filter.name)
+ end
+ filter.enable = true
+end
+
+function disable_hook(list, filter)
+ if not filter then
+ return
+ end
+ local l = list.list
+ local found = false
+ while l and not found do
+ found = (l.hook == filter)
+ l = l.next
+ end
+ if found then
+ printks(froot, "id=%04x disabled\n", filter.id)
+ filter.enable = false
+ else
+ printks(filter, "disabled\n", filter.id)
+ filter.enable = false
+ end
+end
+
+prev_filter = nil
+
+function walk_pre_hooks(list, action)
+ if list == nil or list.list == nil then
+ return false
+ end
+ local logged = false
+ local l = list.list
+ local f = nil
+
+ local no_base_check = true
+ if list == io_hooks or list == mem_hooks then
+ no_base_check = false
+ end
+
+ while l and not logged do
+ f = l.hook
+ if no_base_check or action.addr >= f.base and action.addr < f.base + f.size then
+ if f.enable and f.pre then
+ logged = f.pre(f, action)
+ end
+ end
+ l = l.next
+ end
+
+ if prev_filter ~= f and not action.ignore then
+ prev_filter = f
+ new_parent_action()
+ end
+ if action.dropped then
+ action.to_hw = false
+ action.to_qemu = false
+ end
+end
+
+function walk_post_hooks(list, action)
+ if list == nil or list.list == nil then
+ return false
+ end
+ local logged = false
+ local l = list.list
+ local f = nil
+
+ local no_base_check = true
+ if list == io_hooks or list == mem_hooks then
+ no_base_check = false
+ end
+
+ while l and not logged do
+ f = l.hook
+ if no_base_check or action.addr >= f.base and action.addr < f.base + f.size then
+ if f.enable and f.post then
+ if no_base_check then
+ -- cpuid or cpumsr
+ logged = f.post(f, action)
+ else
+ -- io or mem
+ if f.post(f, action) then
+ action.f = f
+ logged = f.hide and not log_everything
+ end
+ end
+ end
+ end
+ l = l.next
+ end
+end
+
+function generic_io_bar(bar)
+ if not bar.f then
+ local f = {}
+ f.id = -1
+ f.pre = handle_action
+ f.post = io_base_post
+ f.hide = true
+ f.name = bar.name
+ f.size = bar.size
+ bar.f = f
+ end
+ bar.f.base = bit32.band(bar.val, bit32.bnot(bar.size-1))
+ if (bar.f.base ~= 0) then
+ enable_hook(io_hooks, bar.f)
+ else
+ disable_hook(io_hooks, bar.f)
+ end
+end
+
+function generic_mmio_bar(bar)
+ if not bar.f then
+ local f = {}
+ f.id = -1
+ f.pre = handle_action
+ f.post = mem_base_post
+ f.hide = true
+ f.name = bar.name
+ f.size = bar.size
+ bar.f = f
+ end
+ bar.f.base = bit32.band(bar.val, bit32.bnot(bar.size-1))
+ if bar.f.base ~= 0 then
+ enable_hook(mem_hooks, bar.f)
+ else
+ disable_hook(mem_hooks, bar.f)
+ end
+end
+
+PRE_HOOK = 1
+POST_HOOK = 2
+
+function handle_action(f, action)
+ action.to_hw = true
+ return true
+end
+
+function drop_action(f, action, data)
+ if action.stage == POST_HOOK then
+ printk(f, action, "ERROR: Cannot drop action in a post-hook.\n")
+ return true
+ end
+ action.dropped = true
+ action.data = data
+ return true
+end
+
+function ignore_action(f, action)
+ action.ignore = true
+end
+
+function fake_action(f, action, data)
+ if action.stage == POST_HOOK and action.write then
+ printk(f, action, "ERROR: Cannot fake write in a post-hook.\n")
+ return true
+ end
+ action.faked = true
+ action.data = data
+ return true
+end
+
+
+function skip_filter(f, action)
+ return false
+end
+
+function pre_action(action, dir_wr, addr, size, data)
+ action.stage = PRE_HOOK
+ -- CS:IP logging
+ action.cs = regs.cs
+ action.eip = regs.eip
+ action.parent_id = 0
+ action.my_id = 0
+
+ -- no filter, not filtered
+ action.f = nil
+ action.ignore = false
+ action.undefined = false
+ action.faked = false
+ action.dropped = false
+ action.to_hw = false
+ action.to_qemu = false
+
+ action.write = dir_wr
+ action.addr = addr
+
+ action.data = 0
+ action.size = size
+ if action.write then
+ if size == 1 then
+ action.data = bit32.band(0xff, data)
+ elseif size == 2 then
+ action.data = bit32.band(0xffff, data)
+ elseif size == 4 then
+ action.data = bit32.band(0xffffffff, data)
+ end
+ end
+end
+
+function post_action(action, data)
+ action.stage = POST_HOOK
+ action.parent_id = current_parent_id
+ action.my_id = action_id()
+
+ if not action.write then
+ if not action.faked and not action.dropped then
+ action.data = data
+ end
+ end
+end
+
+function load_regs(regs, eax, ebx, ecx, edx)
+ regs.eax = eax
+ regs.ebx = ebx
+ regs.ecx = ecx
+ regs.edx = edx
+end
+
+
diff --git a/SerialICE/simba/interface.lua b/SerialICE/simba/interface.lua
new file mode 100644
index 0000000..48ff8de
--- /dev/null
+++ b/SerialICE/simba/interface.lua
@@ -0,0 +1,161 @@
+
+-- IO, MMIO, RAM and ROM access
+io_action = {}
+mem_action = {}
+
+IO_READ = false
+IO_WRITE = true
+MEM_READ = false
+MEM_WRITE = true
+
+-- CPUID and CPU MSR
+MSR_READ = false
+MSR_WRITE = true
+CPUID = false
+
+cpu_action = {}
+cpu_action.rin = {}
+cpu_action.rout = {}
+
+
+
+-- SerialICE_io_read_filter is the filter function for IO reads.
+--
+-- Parameters:
+-- addr IO port to be read
+-- size Size of the IO read
+-- Return values:
+-- to_hw True if the read should be directed to the target
+-- to_qemu True if the read should be directed to Qemu
+
+function SerialICE_io_read_filter(addr, size)
+ pre_action(io_action, IO_READ, addr, size, 0)
+ walk_pre_hooks(io_hooks, io_action)
+ return io_action.to_hw, io_action.to_qemu
+end
+
+-- Parameters:
+-- data Data from hw or Qemu
+-- Return values:
+-- result Data to give back to Qemu
+
+function SerialICE_io_read_log(data)
+ post_action(io_action, data)
+ walk_post_hooks(io_hooks, io_action)
+ return io_action.data
+end
+
+-- SerialICE_io_write_filter is the filter function for IO writes.
+--
+-- Parameters:
+-- addr IO port to be written to
+-- size Size of the IO write
+-- data Data to be written to
+-- Return values:
+-- to_hw True if the write should be directed to the target
+-- to_qemu True if the write should be directed to Qemu
+-- data Data to be written (possible changed in filter)
+
+function SerialICE_io_write_filter(addr, size, data)
+ pre_action(io_action, IO_WRITE, addr, size, data)
+ walk_pre_hooks(io_hooks, io_action)
+ return io_action.to_hw, io_action.to_qemu, io_action.data
+end
+
+function SerialICE_io_write_log()
+ post_action(io_action)
+ walk_post_hooks(io_hooks, io_action)
+end
+
+
+
+
+-- SerialICE_memory_read_filter is the filter function for memory reads
+--
+-- Parameters:
+-- addr memory address to be read
+-- size Size of the memory read
+-- Return values:
+-- to_hw True if the read should be directed to the target
+-- to_qemu True if the read should be directed to Qemu
+
+function SerialICE_memory_read_filter(addr, size)
+ pre_action(mem_action, MEM_READ, addr, size, 0)
+ walk_pre_hooks(mem_hooks, mem_action)
+ return mem_action.to_hw, mem_action.to_qemu
+end
+
+function SerialICE_memory_read_log(data)
+ post_action(mem_action, data)
+ walk_post_hooks(mem_hooks, mem_action)
+ return mem_action.data
+end
+
+
+-- SerialICE_memory_write_filter is the filter function for memory writes
+--
+-- Parameters:
+-- addr memory address to write to
+-- size Size of the memory write
+-- data Data to be written
+-- Return values:
+-- to_hw True if the write should be directed to the target
+-- to_qemu True if the write should be directed to Qemu
+-- result Data to be written (may be changed in filter)
+
+function SerialICE_memory_write_filter(addr, size, data)
+ pre_action(mem_action, MEM_WRITE, addr, size, data)
+ walk_pre_hooks(mem_hooks, mem_action)
+ return mem_action.to_hw, mem_action.to_qemu, mem_action.data
+end
+
+function SerialICE_memory_write_log()
+ post_action(mem_action, 0)
+ walk_post_hooks(mem_hooks, mem_action)
+end
+
+function SerialICE_msr_read_filter(addr)
+ pre_action(cpu_action, MSR_READ, 0, 0, 0)
+ load_regs(cpu_action.rin, 0, 0, addr, 0)
+
+ walk_pre_hooks(cpumsr_hooks, cpu_action)
+ return cpu_action.to_hw, cpu_action.to_qemu
+end
+
+function SerialICE_msr_read_log(hi, lo)
+ local rout = cpu_action.rout
+ post_action(cpu_action, 0)
+ load_regs(cpu_action.rout, lo, 0, 0, hi)
+ walk_post_hooks(cpumsr_hooks, cpu_action)
+ return rout.edx, rout.eax
+end
+
+function SerialICE_msr_write_filter(addr, hi, lo)
+ local rin = cpu_action.rin
+ pre_action(cpu_action, MSR_WRITE, 0, 0, 0)
+ load_regs(cpu_action.rin, lo, 0, addr, hi)
+ walk_pre_hooks(cpumsr_hooks, cpu_action)
+ return cpu_action.to_hw, cpu_action.to_qemu, rin.edx, rin.eax
+end
+
+function SerialICE_msr_write_log()
+ post_action(cpu_action, 0)
+ load_regs(cpu_action.rout, 0, 0, 0, 0)
+ walk_post_hooks(cpumsr_hooks, cpu_action)
+end
+
+function SerialICE_cpuid_filter(eax, ecx)
+ pre_action(cpu_action, CPUID, 0, 0, 0)
+ load_regs(cpu_action.rin, eax, 0, ecx, 0)
+ walk_pre_hooks(cpuid_hooks, cpu_action)
+ return cpu_action.to_hw, cpu_action.to_qemu
+end
+
+function SerialICE_cpuid_log(eax, ebx, ecx, edx)
+ local rout = cpu_action.rout
+ post_action(cpu_action, 0)
+ load_regs(cpu_action.rout, eax, ebx, ecx, edx)
+ walk_post_hooks(cpuid_hooks, cpu_action)
+ return rout.eax, rout.ebx, rout.ecx, rout.edx
+end
+
diff --git a/SerialICE/simba/memory.lua b/SerialICE/simba/memory.lua
new file mode 100644
index 0000000..11bc6ed
--- /dev/null
+++ b/SerialICE/simba/memory.lua
@@ -0,0 +1,198 @@
+
+-- **********************************************************
+-- ROM access
+
+function mem_qemu_rom_pre(f, action)
+ action.to_hw = false
+ action.to_qemu = true
+ -- Reads from ROM space do not count for filter change.
+ if not action.write then
+ ignore_action(f, action)
+ end
+ return true
+end
+
+function mem_rom_post(f, action)
+ if not action.write then
+ return true
+ end
+ -- Writes to ROM space fall-thru to the fallback filter,
+ -- so they get logged there.
+ return false
+end
+
+filter_rom_low = {
+ id = -1,
+ name = "ROM_LO",
+ pre = mem_qemu_rom_pre,
+ post = mem_rom_post,
+ hide = hide_rom_access,
+ base = 0xE0000,
+ size = 0x20000
+}
+filter_rom_high = {
+ id = -1,
+ name = "ROM_HI",
+ pre = mem_qemu_rom_pre,
+ post = mem_rom_post,
+ hide = hide_rom_access,
+ base = rom_base,
+ size = rom_size,
+}
+
+-- **********************************************************
+-- CAR access
+
+function car_qemu_only(f, action)
+ action.to_hw = false
+ action.to_qemu = true
+ return true
+end
+
+function car_post(f, action)
+ return true
+end
+
+function new_car_region(start, size)
+ f = {}
+ f.id = -1
+ f.name = "CAR"
+ f.base = start
+ f.size = size
+ f.pre = car_qemu_only
+ f.post = car_post
+ f.hide = true
+ enable_hook(mem_hooks, f)
+ SerialICE_register_physical(start, size)
+end
+
+
+-- **********************************************************
+-- RAM access.
+
+-- In the beginning, during RAM initialization, it is essential that
+-- all DRAM accesses are handled by the target, or RAM will not work
+-- correctly. After RAM initialization, RAM access has no "special"
+-- meaning anymore, so we can just use Qemu's memory (and thus get
+-- an incredible speed-up)
+
+-- Not catching the end of RAM init is not problematic, except
+-- that it makes decompression of the BIOS core to RAM incredibly
+-- slow as the decompressor inner loop has to be fetched
+-- permanently from the target (several reads/writes per
+-- decompressed byte).
+
+ram_is_initialized = false
+
+-- This is handled by SerialICE but *NOT* exclusively.
+-- Writes end up in Qemu memory, too
+function mem_ram_low(f, action)
+ if ram_is_initialized then
+ -- RAM init is done. Send all RAM accesses
+ -- to Qemu. Using the target as storage would
+ -- only slow execution down.
+ action.to_hw = false
+ action.to_qemu = true
+ else
+ -- RAM init has not been marked done yet.
+ -- so send reads to the target only.
+ action.to_hw = true
+ action.to_qemu = action.write
+ end
+ return true
+end
+
+-- SMI/VGA writes go to target and qemu
+-- SMI/VGA reads come from target
+function mem_smi_vga(f, action)
+ if action.write then
+ action.to_hw = true
+ action.to_qemu = true
+ else
+ action.to_hw = true
+ action.to_qemu = false
+ end
+ return true
+end
+
+
+function mem_post_pre_ram_only(f, action)
+ return ram_is_initialized
+end
+
+filter_ram_low = {
+ id = -1,
+ name = "MEM",
+ pre = mem_ram_low,
+ post = mem_post_pre_ram_only,
+ hide = true,
+ base = 0x0,
+ size = 0xa0000
+}
+
+filter_smi_vga = {
+ id = -1,
+ name = "SMI_VGA",
+ pre = mem_smi_vga,
+ post = mem_post,
+ hide = true,
+ base = 0x000a0000,
+ size = 0x00010000,
+}
+
+filter_ram_low_2 = {
+ id = -1,
+ name = "MEM",
+ pre = mem_ram_low,
+ post = mem_post_pre_ram_only,
+ hide = true,
+ base = 0xc0000,
+ size = 0x20000
+}
+
+
+function mem_target_only(f, action)
+ action.to_hw = true
+ action.to_qemu = false
+ return true
+end
+
+-- 3.25GB RAM. This is handled by SerialICE.
+-- FIXME: use TOLM here
+
+-- We refrain from backing up this memory in Qemu because Qemu would
+-- need lots of ram on the host and firmware usually does not intensively
+-- use high memory anyways.
+filter_ram_high = {
+ id = -1,
+ name = "MEM",
+ pre = mem_target_only,
+ post = mem_post_pre_ram_only,
+ hide = true,
+ base = 0x100000,
+ size = 0xd0000000 - 0x100000
+}
+
+
+function ram_enabled()
+ return ram_is_initialized
+end
+
+function enable_ram()
+
+ enable_hook(mem_hooks, filter_ram_low)
+ enable_hook(mem_hooks, filter_smi_vga)
+ enable_hook(mem_hooks, filter_ram_low_2)
+ enable_hook(mem_hooks, filter_ram_high)
+
+ -- Register low RAM 0x00000000 - 0x000dffff
+ SerialICE_register_physical(0x00000000, 0xa0000)
+ -- SMI/VGA memory should go to the target...
+ SerialICE_register_physical(0x000c0000, 0x20000)
+ --printf("Low RAM accesses are now directed to Qemu.\n")
+ ram_is_initialized = true
+end
+
+
+
+
diff --git a/SerialICE/simba/output.lua b/SerialICE/simba/output.lua
new file mode 100644
index 0000000..41210da
--- /dev/null
+++ b/SerialICE/simba/output.lua
@@ -0,0 +1,71 @@
+
+
+froot = {
+ id = 0,
+ name = "SerialICE",
+}
+
+fresource = {
+ id = -1,
+ name = "Resource",
+}
+
+-- -------------------------------------------------------------------
+-- logging functions
+
+function printf(s,...)
+ return io.write(s:format(...))
+end
+
+function printk(f, action, fmt, ...)
+ printf("[%04x:%04x] ", action.cs, action.eip)
+ printf("%04x.%04x ", action.parent_id, action.my_id)
+
+ local str = " "
+ if action.dropped or action.faked then
+ str = "!"
+ end
+ if action.undefined then
+ str = "#"
+ end
+
+ if action.f then
+ printf("%s %s,%s: ", str, f.name, action.f.name)
+ printf(fmt, ...)
+ else
+ printf("%s %s: ", str, f.name)
+ printf(fmt, ...)
+ end
+end
+
+function printks(f, fmt, ...)
+ printf("[%04x:%04x] ", 0, 0)
+ printf("%04x.%04x ", 0, 0)
+ printf(" %s: ", f.name)
+ printf(fmt, ...)
+end
+
+function trim (s)
+ return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
+end
+
+function size_suffix(size)
+ if size == 1 then return "b"
+ elseif size == 2 then return "w"
+ elseif size == 4 then return "l"
+ elseif size == 8 then return "ll"
+ else return string.format("invalid size: %d", size)
+ end
+end
+
+function size_data(size, data)
+ if size == 1 then return string.format("%02x", data)
+ elseif size == 2 then return string.format("%04x", data)
+ elseif size == 4 then return string.format("%08x", data)
+ elseif size == 8 then return string.format("%16x", data)
+ else return string.format("Error: size=%x", size)
+ end
+end
+
+
+
diff --git a/SerialICE/simba/serialice.lua b/SerialICE/simba/serialice.lua
new file mode 100644
index 0000000..c179f8c
--- /dev/null
+++ b/SerialICE/simba/serialice.lua
@@ -0,0 +1,69 @@
+-- SerialICE
+--
+-- Copyright (c) 2009 coresystems GmbH
+-- Copyright (c) 2012 Kyösti Mälkki <kyosti.malkki(a)gmail.com>
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a copy
+-- of this software and associated documentation files (the "Software"), to deal
+-- in the Software without restriction, including without limitation the rights
+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+-- copies of the Software, and to permit persons to whom the Software is
+-- furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+-- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+-- THE SOFTWARE.
+--
+
+io.write("SerialICE: Starting LUA script\n")
+
+
+-- Set to "false" to show undecoded access for the specified class
+hide_rom_access = true
+
+-- Set to "true" to log every memory and IO access
+log_everything = false
+
+
+rom_size = 4 * 1024 * 1024
+rom_base = 0x100000000 - rom_size
+
+
+-- --------------------------------------------------------------------
+-- This initialization is executed right after target communication
+-- has been established
+
+dofile("interface.lua")
+dofile("output.lua")
+dofile("hooks.lua")
+dofile("core_io.lua")
+dofile("memory.lua")
+dofile("cpu.lua")
+
+function do_minimal_setup()
+ enable_hook(io_hooks, filter_io_fallback)
+ enable_hook(mem_hooks, filter_mem_fallback)
+ enable_hook(cpumsr_hooks, filter_cpumsr_fallback)
+ enable_hook(cpuid_hooks, filter_cpuid_fallback)
+ enable_hook(mem_hooks, filter_rom_low)
+ enable_hook(mem_hooks, filter_rom_high)
+end
+
+function do_default_setup()
+ enable_ram()
+end
+
+do_minimal_setup()
+do_default_setup()
+
+printks(froot, "LUA script initialized.\n")
+
+return true
+
1
0
New patch to review for serialice: 8b3bcef Add CPUID and CPU MSR filters
by Kyösti Mälkki Oct. 28, 2012
by Kyösti Mälkki Oct. 28, 2012
Oct. 28, 2012
Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1643
-gerrit
commit 8b3bcef891346f02b3945f700d734ef1af695aeb
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Sun Oct 28 14:00:19 2012 +0200
Add CPUID and CPU MSR filters
MSR filter prevents microcode update on the target.
CPUID filter fakes CPU is single-core.
Change-Id: I26479bae215dafe0b1bc114951e04c927423759e
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
SerialICE/simba/cpu.lua | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/SerialICE/simba/cpu.lua b/SerialICE/simba/cpu.lua
index 00162ae..be04825 100644
--- a/SerialICE/simba/cpu.lua
+++ b/SerialICE/simba/cpu.lua
@@ -75,3 +75,57 @@ filter_cpuid_fallback = {
post = cpuid_post,
}
+
+
+function multicore_pre(f, action)
+ return skip_filter(f, action)
+end
+
+function multicore_post(f, action)
+ local rout = action.rout
+ local rin = action.rin
+ -- Set number of cores to 1 on Core Duo and Atom to trick the
+ -- firmware into not trying to wake up non-BSP nodes.
+ if not action.write and rin.eax == 0x01 then
+ rout.ebx = bit32.band(0xff00ffff, rout.ebx);
+ rout.ebx = bit32.bor(0x00010000, rout.ebx);
+ fake_action(f, action, 0)
+ end
+ return skip_filter(f, action)
+end
+
+filter_multiprocessor = {
+ id = -1,
+ name = "Multiprocessor Count",
+ pre = multicore_pre,
+ post = multicore_post,
+}
+
+-- Intel CPU microcode update
+function intel_microcode_pre(f, action)
+ if action.rin.ecx == 0x79 then
+ --action.dropped = true
+ --action.rout.edx = 0
+ --action.rout.eax = 0xffff0000
+ return drop_action(f, action)
+ end
+ return skip_filter(f, action)
+end
+
+-- Intel CPU microcode revision check
+-- Fakes microcode revision of my 0x6f6 Core 2 Duo Mobile
+function intel_microcode_post(f, action)
+ if action.rin.ecx == 0x8b then
+ action.rout.edx = 0xc7
+ action.rout.eax = 0
+ return fake_action(f, action, 0)
+ end
+ return skip_filter(f, action)
+end
+
+filter_intel_microcode = {
+ id = -1,
+ name = "Microcode Update",
+ pre = intel_microcode_pre,
+ post = intel_microcode_post,
+}
1
0
Oct. 28, 2012
Kyösti Mälkki (kyosti.malkki(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1644
-gerrit
commit eeb22786e622d85091719d3b8d0b62865913424f
Author: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
Date: Sun Oct 28 11:01:47 2012 +0200
Add log replayer
If you create the log from serialice with log_everything=true,
you can modify the filters and pipe the logfile through the replayer
without having to run Qemu again. This mostly works with old logfiles
created with the single-file script too.
$ cat qemu_logfile.txt | lua replay.lua
Change-Id: I80f94f6cdb13b1f52188f4b9560ec040fb831fe8
Signed-off-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
---
SerialICE/simba/replay.lua | 186 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 186 insertions(+)
diff --git a/SerialICE/simba/replay.lua b/SerialICE/simba/replay.lua
new file mode 100644
index 0000000..fcfabf3
--- /dev/null
+++ b/SerialICE/simba/replay.lua
@@ -0,0 +1,186 @@
+
+
+function SerialICE_register_physical()
+end
+
+function SerialICE_system_reset()
+end
+
+SerialICE_mainboard = "undetected"
+
+regs = { eax, ebc, ecx, edx, cs=0, eip=0, ds, es, ss, gs, fs, }
+ids = { parent, this, }
+
+function replay_io(dir_wr, addr, size, data)
+ pre_action(io_action, dir_wr, addr, size, data)
+ walk_pre_hooks(io_hooks, io_action)
+ io_action.data = data
+ post_action(io_action, data)
+ walk_post_hooks(io_hooks, io_action)
+end
+
+function replay_mem(dir_wr, addr, size, data)
+ pre_action(mem_action, dir_wr, addr, size, data)
+ walk_pre_hooks(mem_hooks, mem_action)
+ mem_action.data = data
+ post_action(mem_action, data)
+ walk_post_hooks(mem_hooks, mem_action)
+end
+
+function replay_unknown(str)
+ local dummy = {}
+ pre_action(dummy, false, 0, 0, 0)
+ post_action(dummy, 0)
+ io.write(string.format("[%04x:%04x] %04x.%04x %s\n",
+ regs.cs, regs.eip, ids.parent, ids.this, str))
+end
+
+function parse_cpu(line)
+ if string.find(line, "CPUID") then
+ replay_unknown(line)
+ return true
+ end
+ if string.find(line, "CPU MSR") then
+ replay_unknown(line)
+ return true
+ end
+ return false
+end
+
+
+function parse_io(line)
+ local io_op = "IO[^:]*:?%s+%a+%s+(%x+)%s+(<?=>?)%s+(%x+)"
+ local found, addr, dir, data
+ found, _, addr, dir, data = string.find(line, io_op)
+ if not found then
+ return false
+ end
+ local naddr = tonumber(addr, 16)
+ local ndata = tonumber(data, 16)
+ local nsize = string.len(data)/2
+ if string.find("<=", dir) then
+ replay_io(true, naddr, nsize, ndata)
+ else
+ replay_io(false, naddr, nsize, ndata)
+ end
+ return true
+end
+
+function parse_mem(line)
+ local mem_op = "MEM[^:]*:?%s+%a+%s+(%x+)%s+(<?=>?)%s+(%x+)"
+ local found, addr, dir, data
+ found, _, addr, dir, data = string.find(line, mem_op)
+ if not found then
+ return false
+ end
+ local naddr = tonumber(addr, 16)
+ local ndata = tonumber(data, 16)
+ local nsize = string.len(data)/2
+ if string.find("<=", dir) then
+ replay_mem(true, naddr, nsize, ndata)
+ else
+ replay_mem(false, naddr, nsize, ndata)
+ end
+ return true
+end
+
+-- Old script already parsed PCI config, synthesize those IOs back.
+function parse_pci(line)
+ local found, bus, dev, fn, reg, dir, data
+ local pci_cfg = "PCI:?%s+(%x):(%x+).(%x+)%s+R.(%x+)%s+(<?=>?)%s+(%x+)"
+ found, _, bus, dev, fn, reg, dir, data = string.find(line, pci_cfg)
+ if not found then
+ local pci_cfg_empty = "PCI:?%s+(%x):(%x+).(%x+)%s+R.(%x+)"
+ if string.find(line, pci_cfg_empty) then
+ return true
+ end
+ return false
+ end
+
+ local nreg = bit32.band(0xfc, tonumber(reg,16))
+ local noff = bit32.band(0x03, tonumber(reg,16))
+ local ndata = tonumber(data,16)
+ local nsize = string.len(data)/2
+
+ replay_io(true, 0xcf8, 4, pci_bdf(tonumber(bus,16), tonumber(dev,16), tonumber(fn,16), nreg))
+ if string.find("<=", dir) then
+ replay_io(true, 0xcfc + noff, nsize, ndata)
+ else
+ replay_io(false, 0xcfc + noff, nsize, ndata)
+ end
+ return true
+end
+
+function parse_headers()
+ while true do
+ local found = false
+ line = io.read("*line")
+ if not found then
+ local board
+ found, _, board = string.find(line, "SerialICE: Mainboard...:%s+(.+)")
+ if found then
+ SerialICE_mainboard = board
+ end
+ end
+-- io.write(line)
+-- io.write("\n")
+ if string.find(line, "LUA script initialized.") then
+ return
+ end
+ end
+end
+
+function parse_file()
+ while true do
+ local iplog = false
+ local found = false
+ local line, str, cs, eip, a, b
+
+ line = io.read("*line")
+ if not line then
+ return
+ end
+
+ regs.cs = 0
+ regs.eip = 0
+ ids.parent = 0
+ ids.this = 0
+ iplog, _, cs, eip, a, b, str = string.find(line, "%[(%x+):(%x+)%]%s+(%x+)[%.:](%x+)...(.*)")
+ if iplog then
+ regs.cs = tonumber(cs, 16)
+ regs.eip = tonumber(eip, 16)
+ ids.parent = tonumber(a, 16)
+ ids.this = tonumber(b, 16)
+ end
+
+ if not iplog then
+ str = line
+ end
+
+ if not found then
+ found = parse_io(str)
+ end
+ if not found then
+ found = parse_pci(str)
+ end
+ if not found then
+ found = parse_mem(str)
+ end
+ if not found then
+ found = parse_cpu(str)
+ end
+ if not found then
+ --replay_unknown(str)
+ end
+ end
+end
+
+parse_headers()
+
+dofile("serialice.lua")
+
+parse_file()
+
+
+
+
1
0