Use of device_t has been abandoned in ramstage.
Change-Id: Ie366a49045940747eb5cc1e38316cce31c5774cb
Signed-off-by: Elyes HAOUAS <ehaouas@noos.fr>
Reviewed-on: https://review.coreboot.org/26251
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
Use of device_t has been abandoned in ramstage.
Change-Id: Id3289c891e8a81c750fc3f5fad0fd16c0f2702fe
Signed-off-by: Elyes HAOUAS <ehaouas@noos.fr>
Reviewed-on: https://review.coreboot.org/26195
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
Braces {} are not necessary for single statement blocks.
Change-Id: I2a2d8672fe3f53450dcfa53dc127b89b4aa6b75e
Signed-off-by: Elyes HAOUAS <ehaouas@noos.fr>
Reviewed-on: https://review.coreboot.org/26201
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
In some cases callers want to know if a file
exists and, if so, what its type is.
Modify cbfs_locate so that if the pointer is non-NULL,
but has the value 0, the type of the file that
matches the name will be returned.
Change-Id: Ic1349d358c3054207ccbccf3825db56784327ad0
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Reviewed-on: https://review.coreboot.org/26279
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Update the gpio configuration structure to the intelblock format.
The resulting configuration is functionally similar (even if some
bits are not identical).
Change-Id: Ide515424c6e1b0cb560b52a7f12909f23fd41e06
Signed-off-by: Julien Viard de Galbert <jviarddegalbert@online.net>
Reviewed-on: https://review.coreboot.org/25424
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
The intelblock code is common code already used by appololake and
cannonlake platform. The denverton platform also use a similar gpio
controller so the intelblock code can be used as well.
Change-Id: I7ecfb5a3527e9c893930149f7b847a41c5dd9374
Signed-off-by: Julien Viard de Galbert <jviarddegalbert@online.net>
Reviewed-on: https://review.coreboot.org/24928
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
In order to use the shared code in intelblock, this patch renames the
denverton specific implementation to not use the same names (for files
and types).
- rename pad_config to remove conflict with soc/.../intelblocks/gpio.h
- rename gpio.c, soc/gpio.h to not conflict with intelblock
Note: There is no functional change in this patch.
Change-Id: Id3f4e2dc0a118e8c864a96a435fa22e32bbe684f
Signed-off-by: Julien Viard de Galbert <jviarddegalbert@online.net>
Reviewed-on: https://review.coreboot.org/24926
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
All those symbols are part of /include/symbols.h file hence
removing from /security/vboot/symbols.h
Change-Id: Id968186e28d6b772a1a6bca200a852407324d6e3
Signed-off-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-on: https://review.coreboot.org/26274
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
The NPCD378 can be found on at least:
* HP Compaq 8200
* HP Compaq 8300
The datasheet is not publicly available, as HP implements lots of
custom hardware. Add basic support for it, based on HP Compaq 8200.
The first eight LDNs seem to be standard nuvoton compatible, except for
LDN4, which is used to control front LED and power in ACPI S3.
LDN8 provides access to HP's proprietary HWM which is accessiable at the LDN's
IOBASE with a size of 0x100 bytes.
The HWM consists of 16 pages with each holding 0xff bytes. The pages can be
selected by writing the page index to IOBASE + 0xff.
TODO:
Reverse engineer the HWM to support fan control.
WARNING:
The remaining LDNs have been guessed and might be wrong!
The serial has been tested and is working.
Change-Id: Ib497fd41b88e9c159eeeffa69bc2bfdccee9cb38
Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-on: https://review.coreboot.org/25384
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This patch ensures that user can pass a function with given argument
list to execute over APs.
BUG=b:74436746
BRANCH=none
TEST=Able to run functions over APs with argument.
Change-Id: I668b36752f6b21cb99cd1416c385d53e96117213
Signed-off-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-on: https://review.coreboot.org/25725
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
In order to extend the MP callback infrastructure prepare for
easier changes by making the AP callback get signalled by a
single pointer to a local variable on the signaller's stack.
When the APs see the callback they will copy the structure
to a local variable and then set the acknowledgement by
clearing out the slot.
The reading and writing to the slots were implemented using inline
assembly which forces a memory access and a compiler barrier.
BUG=b:74436746
Change-Id: Ia46133a49c03ce3ce0e73ae3d30547316c7ec43c
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/26043
Reviewed-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Adapt the programming of initial DLL values for DDR3.
Change-Id: I67e48b4ae6f2076399133ba7b98ab1dfc0e0ab08
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/22993
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Also throws in some minor fixes like the wrong conditional for
bankmod and using real CAS when programming MCHBAR(0x248).
Change-Id: Ia2494684ec66d84d4dc27c6a6b425a33ace6e827
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/19873
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Adds nmode to the sysinfo struct as it is needed later on.
Change-Id: Ia2ca4a200a1c813b2133eb1004fbe248fa3de9ce
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/19872
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
A few values were wrong, but it does not seem to matter all that
much.
Change-Id: I86b70e06c81817854994b7feddf9f3638fd16198
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/19871
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This memory controller supports both DDR2 and DDR3 memory, yet many
functions have ddr2 in their name while not being ddr2 specific.
This patch renames those to avoid confusion.
Change-Id: Ib3d10014f530905155e56fc52706edb4ab9f5630
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/19870
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Since this memory controller supports both DDR2 and DDR3 allow it to
decode both while making the dram type mutually exclusive.
Change-Id: I8dba19ca1e6e6b0a03b56c8de9633f9c1a2eb7d7
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/19869
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Some things in programming registers related to dual channel
interleaved operation were wrong.
This also adds some code that could in the future be used when me is
active and claims some memory for its UMA.
This also uses some more sensible variable names to clarify at least
some of the magic.
This fixes memtest86+ failing with some assymetric DIMM configuration.
TESTED on DG43GT: memtest86+ now succeeds on many more different DIMM
configuration setups (would instantly fail at addresses above 4G on
many configurations).
Change-Id: If84099d27100e57437bf214dc4cf975f67c2ea1f
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/22914
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Add an lpc_acpi_name function to report its namespace as "LIBR"
rather than some fallback value which seems to vary. This repair
is required for the LPC TPM device to register its presence
without blowing up the table and preventing the payload from
seeing the SATA device.
Before change (but after other similar change to PCI0), the
TPM device reported itself as:
\_SB.PCI0.LPC0.TPM
After change, the TPM device reports as:
\_SB.PCI0.LIBR.TPM
which is consistent with the tables AGESA generates.
Change-Id: Ifa3a0e386cc00062855331e5f9d1c00d6541c238
Signed-off-by: Kevin Cody-Little <kcodyjr@gmail.com>
Reviewed-on: https://review.coreboot.org/26205
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Add a function domain_acpi_name to return "PCI0", rather than
falling back to the parent' device's "\_SB" label. This repair is
required for the LPC TPM device to register its presence without
blowing up the table and preventing the payload from finding SATA.
Before change, the TPM device reported as:
\_SB.\_SB.LPC0.TPM
After change, the TPM device reports as:
\_SB.PCI0.LPC0.TPM
A separate change submission will correct "LPC0" as well.
Change-Id: I5e8d4715c9b42f50c84dd65818e4b0fdfc9d54f9
Signed-off-by: Kevin Cody-Little <kcodyjr@gmail.com>
Reviewed-on: https://review.coreboot.org/26204
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Nico Huber <nico.h@gmx.de>
I'm increasing the max because when AGESA tracing is enabled it will use
over 120 entries. I added some padding to the number incase more probes
are added. This only affects ramstage so the extra ram shouldn't matter.
BUG=b:64549506
TEST=boot on grunt and ran cbmem -t
Change-Id: I7a3d2d09c91c9e302d139e7f65fa9c85c4594de4
Signed-off-by: Raul E Rangel <rrangel@chromium.org>
Reviewed-on: https://review.coreboot.org/26234
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This will allow loading of programs that are more than one type,
e.g. ramstage type might now be a stage or payload.
Further, unknown types of 0 are dangerous, make it a real value.
Change-Id: Ieb4eeb7c5934bddd9046ece8326342db0d76363c
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Reviewed-on: https://review.coreboot.org/26242
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Had 0x2e hardcoded, which is often the SuperIO chip. Instead,
pull the port from the PNP tree generated from devicetree.cb,
where either 0x4e or 0x2e will be specified.
Change-Id: I4a92693f8acd3a1618cefcdf6b25eb22a727e20f
Signed-off-by: Kevin Cody-Little <kcodyjr@gmail.com>
Reviewed-on: https://review.coreboot.org/26203
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
If the timestamp entries are added out of order, the duration
calculation will be wrong.
AGESA collects timestamp data through all the stages. Then in AmdInitPost
it asks for a buffer to write TP_Perf_STRUCT into. agesawrapper will then
take the data and call timestamp_add on each entry. This results in
the entries being out of order.
TEST=Built firmware for grunt that manually added entries and then ran
cbmem -t/-T to verify the entries were in the correct order.
Change-Id: I6946a844b71d714141b3372e4c43807cfe3528ad
Signed-off-by: Raul E Rangel <rrangel@chromium.org>
Reviewed-on: https://review.coreboot.org/26168
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Reviewed-by: Martin Roth <martinroth@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This is based on the code from the 8470p port. Tested on the quad
core/quad SODIMM version. This laptop uses discrete MXM 3.0b graphics
cards. Tested working with both Quadro K3000M and GTX 980M 8GB. The
laptop must be completely disassembled down to the motherboard to
perform the initial flash, subsequent flashes can be done internally
via flashrom. There is a simple mod that can be performed to make
subsequent external flashes easier in case of a brick, I'll put more
information on this on the wiki later. The lack of an MXM structure
built in to the firmware causes the GPU to enter a mode with nerfed
performance, there is a workaround though, I'll add this to the wiki
as well. I have no info on EHCI debugging.
Tested and working:
- memory: 4G+4G, 4G+4G+4G+4G
- Linux (Debian Stretch with kernel 4.9.0) booted from SeaBIOS payload
with graphics init disabled in coreboot. I allowed SeaBIOS to load the
VBIOS from the MXM.
- WLAN
- keyboard, trackpoint and touchpad
- USB
- serial port on dock
- fan control
- VGA
- DisplayPort
- Audio
- Both HDD SATA ports, ODD SATA, eSATA
- S3 with SeaBIOS 1.11, SERCON must be disabled
- Brightness and volume FN keys
- Mute and calculator hotkeys
- Status LEDs
- Bluetooth
Not working:
- GRUB2 as payload will freeze. Has something to do with at_keyboard
module. The built in keyboard requires this module to function though.
- Sleep FN key
- WiFi toggle and internet browser hotkeys
- S3 fails to resume (restarts) if the laptop is removed from AC power,
or gets unplugged and then plugged back in while suspended. Sleep
status LEDs remain normal during this process.
Change-Id: Ic4ff64e9cf0c7a51ac48ca2fe6fe8beab02e9f9a
Signed-off-by: Robert Reeves <xiinc37@gmail.com>
Reviewed-on: https://review.coreboot.org/23651
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
The VIA CPUs allow setting the CPUID vendor, which is best read as
a character string.
Change-Id: I67f77ca75f7d77e47b3ba09bad904df5805e373a
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Reviewed-on: https://review.coreboot.org/18257
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martinroth@google.com>
VIA c3 & C7 use the the family of 0x6 and model 10, but are not quite
Pentium III.
Change-Id: I85e9853b42cfd20db46db0bd244620d6813bc826
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Reviewed-on: https://review.coreboot.org/18256
Reviewed-by: Martin Roth <martinroth@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Copies the common/env_ctrl support code from the it8728f driver.
Tested on an ASUS AM1I-A using Linux 4.16.7-gentoo as payload,
and booting userspace without a kexec call.
Prior to this change, an error was given during boot:
it87 it87.656: Detected broken BIOS defaults, disabling PWM interface
After this change, the message is gone, and PWM fan control works
through the /sys/class/hwmon interface.
Change-Id: Id97c4ec19562e7c78308c5afe6ff7c938922c9e7
Signed-off-by: Kevin Cody-Little <kcodyjr@gmail.com>
Reviewed-on: https://review.coreboot.org/26224
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This reverts commit 0ff9daac45.
It points to a stale commit under review; i.e. not to a commit on
blob.git's master branch like it's supposed to.
Change-Id: I19cb8a32b3971c3104e381673ca08ae4d3979128
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/26241
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-by: David Hendricks <david.hendricks@gmail.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This change adds board-specific implementation of
mainboard_vbt_filename which returns "vbt.bin" by default. This is in
preparation to allow multiple vbt binaries to be added to single
image. More sku_id specific names will be added in follow-up CLs.
BUG=b:79396300
Change-Id: I3821d55bfbe9e5773bd2eb0b0003045a80158d8c
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://review.coreboot.org/26227
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
My bad, it seems the acronym for Broadwell is BDW, and not BDL, so
I'm renaming librem_bdl into librem_bdw and changing the KConfig
options accordingly.
Change-Id: I8e992aa3474863236adf8893fcbe37c1b801fa25
Signed-off-by: Youness Alaoui <youness.alaoui@puri.sm>
Reviewed-on: https://review.coreboot.org/26237
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
In 4a3956d7 (drivers/intel/gma, soc/intel/common: improve
cooperation) the vbt_size parameter was not honored leading to
the use of unitialized variables from the caller. Instead, keep
track of if the vbt is already loaded by using the size returned
from the load. If it's non-zero the vbt has been loaded.
BUG=b:79562868
Change-Id: Ia1c47f0d982fae74e0223922f83943c68a846aa9
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/26236
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Reviewed-by: Subrata Banik <subrata.banik@intel.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Current VBT setting for T8 is only 1ms which is under Innolux
N116BCA-EA1 panel's spec.
Modify T8 to 100ms.
(Innolux's panel's spec requires T8 needs to be greater than 80ms
BUG=b:78541692
BRANCH=master
TEST=emerge-coral depthcharge coreboot chromeos-bootimage
Run on DUT and check panel sequence meets spec.
Change-Id: I5f9103aca7871095a828a74cd6a97e1951adb81f
Signed-off-by: Ren Kuo <Ren.Kuo@quantatw.com>
Reviewed-on: https://review.coreboot.org/26214
Reviewed-by: Ren Kuo <ren.kuo@quantatw.com>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Without it the PS/2 keyboard doesn't work after booting into the OS.
Change-Id: Idcb0ea0779fcd5dfd6e0fbf33a532ecf0caec420
Signed-off-by: Iru Cai <mytbk920423@gmail.com>
Reviewed-on: https://review.coreboot.org/26131
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Adding new librem_bdl variant for the Librem 15 v2, which is very similar
to Librem 13 v1, with the following differences:
- SATA ports 0 and 1 instead of 0 and 3
- SATA DTLE IOBP value is 7 instead of 9 for port 0
- There is no LAN device
- There are two SODIMM slots, and DQs are interleaved
- USB ports are different
Change-Id: Ifaca382a540d085e6c919daa992a0fbd52643a5b
Signed-off-by: Youness Alaoui <youness.alaoui@puri.sm>
Reviewed-on: https://review.coreboot.org/26184
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Convert the purism/librem13v1 to a variant setup, in
preparation for adding the librem15v2 board as a new variant.
The Librem 13 v1 and Librem 15 v2 are nearly identical, so
this minimizes new code to add support for the latter.
Also update the URL in board_info to an archive.org link.
Change-Id: I00bb82b9e895e2464ddaa92915c01ce0e35933a2
Signed-off-by: Youness Alaoui <youness.alaoui@puri.sm>
Reviewed-on: https://review.coreboot.org/26183
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Use of device_t has been abandoned in ramstage.
Change-Id: I69c8b95ff1937c0b08147d9e26a3118c58129cf5
Signed-off-by: Elyes HAOUAS <ehaouas@noos.fr>
Reviewed-on: https://review.coreboot.org/26197
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
This commit adds support for writing ACPI _PLD structures that
describe the physical location of a device to the OS.
This can be used by any device with a physical connector, but is
required when defining USB ports for the OS.
A simple function is provided that generates a generic _PLD
structure for USB ports based on the USB port type.
Change-Id: Ic9cf1fd158eca80ead21b4725b37ab3c36b000f3
Signed-off-by: Duncan Laurie <dlaurie@google.com>
Reviewed-on: https://review.coreboot.org/26171
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This commit adds support for writing ACPI _UPC structures that
help describe USB ports for the OS.
This is a simple structure format which indicates what type of
port it is and whether it is connectable. It should be paired
with an ACPI _PLD structure to define USB ports for the OS.
Change-Id: Ide3768f60f96e9ad7f919ad3fb11d91045dc174a
Signed-off-by: Duncan Laurie <dlaurie@google.com>
Reviewed-on: https://review.coreboot.org/26170
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>