@@ -390,6 +390,7 @@ struct brcmf_pciedev_info {
390390 bool in_irq ;
391391 struct pci_dev * pdev ;
392392 char fw_name [BRCMF_FW_NAME_LEN ];
393+ char sig_name [BRCMF_FW_NAME_LEN ];
393394 char nvram_name [BRCMF_FW_NAME_LEN ];
394395 char clm_name [BRCMF_FW_NAME_LEN ];
395396 char txcap_name [BRCMF_FW_NAME_LEN ];
@@ -398,8 +399,7 @@ struct brcmf_pciedev_info {
398399 const struct brcmf_pcie_reginfo * reginfo ;
399400 void __iomem * regs ;
400401 void __iomem * tcm ;
401- u32 ram_base ;
402- u32 ram_size ;
402+ u32 fw_size ;
403403 struct brcmf_chip * ci ;
404404 u32 coreid ;
405405 struct brcmf_pcie_shared_info shared ;
@@ -1803,26 +1803,164 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
18031803 return 0 ;
18041804}
18051805
1806- struct brcmf_random_seed_footer {
1806+ struct brcmf_rtlv_footer {
18071807 __le32 length ;
18081808 __le32 magic ;
18091809};
18101810
1811+ struct brcmf_fw_memmap {
1812+ u32 pad1 [8 ];
1813+ u32 vstatus_start ;
1814+ u32 vstatus_end ;
1815+ u32 fw_start ;
1816+ u32 fw_end ;
1817+ u32 sig_start ;
1818+ u32 sig_end ;
1819+ u32 heap_start ;
1820+ u32 heap_end ;
1821+ u32 pad2 [6 ];
1822+ };
1823+
1824+
1825+ #define BRCMF_BL_HEAP_START_GAP 0x1000
1826+ #define BRCMF_BL_HEAP_SIZE 0x10000
18111827#define BRCMF_RANDOM_SEED_MAGIC 0xfeedc0de
18121828#define BRCMF_RANDOM_SEED_LENGTH 0x100
1829+ #define BRCMF_SIG_MAGIC 0xfeedfe51
1830+ #define BRCMF_VSTATUS_MAGIC 0xfeedfe54
1831+ #define BRCMF_VSTATUS_SIZE 0x28
1832+ #define BRCMF_MEMMAP_MAGIC 0xfeedfe53
1833+ #define BRCMF_END_MAGIC 0xfeed0e2d
1834+
1835+ static int brcmf_alloc_rtlv (struct brcmf_pciedev_info * devinfo , u32 * address , u32 type , size_t length )
1836+ {
1837+ struct brcmf_bus * bus = dev_get_drvdata (& devinfo -> pdev -> dev );
1838+ u32 boundary = devinfo -> ci -> rambase + devinfo -> fw_size +
1839+ BRCMF_BL_HEAP_START_GAP + BRCMF_BL_HEAP_SIZE ;
1840+ u32 start_addr ;
1841+ struct brcmf_rtlv_footer footer = {
1842+ .magic = type ,
1843+ };
1844+
1845+ length = ALIGN (length , 4 );
1846+ start_addr = * address - length - sizeof (struct brcmf_rtlv_footer );
1847+
1848+ if (length > 0xffff || start_addr > * address || start_addr < boundary ) {
1849+ brcmf_err (bus , "failed to allocate 0x%zx bytes for rTLV type 0x%x\n" ,
1850+ length , type );
1851+ return - ENOMEM ;
1852+ }
1853+
1854+ /* Random seed does not use the length check code */
1855+ if (type == BRCMF_RANDOM_SEED_MAGIC )
1856+ footer .length = length ;
1857+ else
1858+ footer .length = length | ((length ^ 0xffff ) << 16 );
1859+
1860+ memcpy_toio (devinfo -> tcm + * address - sizeof (struct brcmf_rtlv_footer ),
1861+ & footer , sizeof (struct brcmf_rtlv_footer ));
1862+
1863+ * address = start_addr ;
1864+
1865+ return 0 ;
1866+ }
18131867
1814- static noinline_for_stack void
1815- brcmf_pcie_provide_random_bytes (struct brcmf_pciedev_info * devinfo , u32 address )
1868+ static noinline_for_stack int
1869+ brcmf_pcie_add_random_seed (struct brcmf_pciedev_info * devinfo , u32 * address )
18161870{
1871+ int err ;
18171872 u8 randbuf [BRCMF_RANDOM_SEED_LENGTH ];
18181873
1874+ err = brcmf_alloc_rtlv (devinfo , address ,
1875+ BRCMF_RANDOM_SEED_MAGIC , BRCMF_RANDOM_SEED_LENGTH );
1876+ if (err )
1877+ return err ;
1878+
1879+ /* Some Apple chips/firmwares expect a buffer of random
1880+ * data to be present before NVRAM
1881+ */
1882+ brcmf_dbg (PCIE , "Download random seed\n" );
1883+
18191884 get_random_bytes (randbuf , BRCMF_RANDOM_SEED_LENGTH );
18201885 memcpy_toio (devinfo -> tcm + address , randbuf , BRCMF_RANDOM_SEED_LENGTH );
1886+
1887+ return 0 ;
1888+ }
1889+
1890+ static int brcmf_pcie_add_signature (struct brcmf_pciedev_info * devinfo ,
1891+ u32 * address , const struct firmware * fwsig )
1892+ {
1893+ int err ;
1894+ struct brcmf_fw_memmap memmap ;
1895+
1896+ brcmf_dbg (PCIE , "Download firmware signature\n" );
1897+
1898+ memset (& memmap , 0 , sizeof (memmap ));
1899+
1900+ memmap .sig_end = * address ;
1901+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_SIG_MAGIC , fwsig -> size );
1902+ if (err )
1903+ return err ;
1904+ memmap .sig_start = * address ;
1905+
1906+ memmap .vstatus_end = * address ;
1907+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_VSTATUS_MAGIC , BRCMF_VSTATUS_SIZE );
1908+ if (err )
1909+ return err ;
1910+ memmap .vstatus_start = * address ;
1911+
1912+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_MEMMAP_MAGIC , sizeof (memmap ));
1913+ if (err )
1914+ return err ;
1915+
1916+ memmap .fw_start = devinfo -> ci -> rambase ;
1917+ memmap .fw_end = memmap .fw_start + devinfo -> fw_size ;
1918+ memmap .heap_start = memmap .fw_end + BRCMF_BL_HEAP_START_GAP ;
1919+ memmap .heap_end = memmap .heap_start + BRCMF_BL_HEAP_SIZE ;
1920+
1921+ if (memmap .heap_end > * address )
1922+ return - ENOMEM ;
1923+
1924+ memcpy_toio (devinfo -> tcm + memmap .sig_start , fwsig -> data , fwsig -> size );
1925+ memset_io (devinfo -> tcm + memmap .vstatus_start , 0 , BRCMF_VSTATUS_SIZE );
1926+ memcpy_toio (devinfo -> tcm + * address , & memmap , sizeof (memmap ));
1927+
1928+ err = brcmf_alloc_rtlv (devinfo , address , BRCMF_END_MAGIC , 0 );
1929+ if (err )
1930+ return err ;
1931+
1932+ return 0 ;
1933+ }
1934+
1935+ static int brcmf_pcie_populate_footers (struct brcmf_pciedev_info * devinfo ,
1936+ u32 * address , const struct firmware * fwsig )
1937+ {
1938+ int err ;
1939+
1940+ /* We only do this for Apple firmwares. If any other
1941+ * production firmwares are found to need this, the condition
1942+ * needs to be adjusted.
1943+ */
1944+ if (!devinfo -> fwseed )
1945+ return 0 ;
1946+
1947+ err = brcmf_pcie_add_random_seed (devinfo , address );
1948+ if (err )
1949+ return err ;
1950+
1951+ if (fwsig ) {
1952+ err = brcmf_pcie_add_signature (devinfo , address , fwsig );
1953+ if (err )
1954+ return err ;
1955+ }
1956+
1957+ return 0 ;
18211958}
18221959
18231960static int brcmf_pcie_download_fw_nvram (struct brcmf_pciedev_info * devinfo ,
1824- const struct firmware * fw , void * nvram ,
1825- u32 nvram_len )
1961+ const struct firmware * fw ,
1962+ const struct firmware * fwsig ,
1963+ void * nvram , u32 nvram_len )
18261964{
18271965 struct brcmf_bus * bus = dev_get_drvdata (& devinfo -> pdev -> dev );
18281966 u32 sharedram_addr ;
@@ -1842,44 +1980,39 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
18421980 (void * )fw -> data , fw -> size );
18431981
18441982 resetintr = get_unaligned_le32 (fw -> data );
1983+ devinfo -> fw_size = fw -> size ;
18451984 release_firmware (fw );
18461985
18471986 /* reset last 4 bytes of RAM address. to be used for shared
18481987 * area. This identifies when FW is running
18491988 */
18501989 brcmf_pcie_write_ram32 (devinfo , devinfo -> ci -> ramsize - 4 , 0 );
18511990
1991+ address = devinfo -> ci -> rambase + devinfo -> ci -> ramsize ;
1992+
18521993 if (nvram ) {
18531994 brcmf_dbg (PCIE , "Download NVRAM %s\n" , devinfo -> nvram_name );
1854- address = devinfo -> ci -> rambase + devinfo -> ci -> ramsize -
1855- nvram_len ;
1995+ address -= nvram_len ;
18561996 memcpy_toio (devinfo -> tcm + address , nvram , nvram_len );
18571997 brcmf_fw_nvram_free (nvram );
18581998
1859- if (devinfo -> fwseed ) {
1860- size_t rand_len = BRCMF_RANDOM_SEED_LENGTH ;
1861- struct brcmf_random_seed_footer footer = {
1862- .length = cpu_to_le32 (rand_len ),
1863- .magic = cpu_to_le32 (BRCMF_RANDOM_SEED_MAGIC ),
1864- };
1865-
1866- /* Some chips/firmwares expect a buffer of random
1867- * data to be present before NVRAM
1868- */
1869- brcmf_dbg (PCIE , "Download random seed\n" );
1870-
1871- address -= sizeof (footer );
1872- memcpy_toio (devinfo -> tcm + address , & footer ,
1873- sizeof (footer ));
1874-
1875- address -= rand_len ;
1876- brcmf_pcie_provide_random_bytes (devinfo , address );
1877- }
1999+ err = brcmf_pcie_populate_footers (devinfo , & address , fwsig );
2000+ if (err )
2001+ brcmf_err (bus , "failed to populate firmware footers err=%d\n" , err );
18782002 } else {
18792003 brcmf_dbg (PCIE , "No matching NVRAM file found %s\n" ,
18802004 devinfo -> nvram_name );
18812005 }
18822006
2007+ release_firmware (fwsig );
2008+
2009+ /* Clear free TCM. This isn't really necessary, but it
2010+ * makes debugging memory dumps a lot easier since we
2011+ * don't get a bunch of junk filling up the free space.
2012+ */
2013+ memset_io (devinfo -> tcm + devinfo -> ci -> rambase + devinfo -> fw_size ,
2014+ 0 , address - devinfo -> fw_size - devinfo -> ci -> rambase );
2015+
18832016 sharedram_addr_written = brcmf_pcie_read_ram32 (devinfo ,
18842017 devinfo -> ci -> ramsize -
18852018 4 );
@@ -2265,11 +2398,12 @@ static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
22652398#define BRCMF_PCIE_FW_NVRAM 1
22662399#define BRCMF_PCIE_FW_CLM 2
22672400#define BRCMF_PCIE_FW_TXCAP 3
2401+ #define BRCMF_PCIE_FW_SIG 4
22682402
22692403static void brcmf_pcie_setup (struct device * dev , int ret ,
22702404 struct brcmf_fw_request * fwreq )
22712405{
2272- const struct firmware * fw ;
2406+ const struct firmware * fw , * fwsig ;
22732407 void * nvram ;
22742408 struct brcmf_bus * bus ;
22752409 struct brcmf_pciedev * pcie_bus_dev ;
@@ -2288,6 +2422,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
22882422 brcmf_pcie_attach (devinfo );
22892423
22902424 fw = fwreq -> items [BRCMF_PCIE_FW_CODE ].binary ;
2425+ fwsig = fwreq -> items [BRCMF_PCIE_FW_SIG ].binary ;
22912426 nvram = fwreq -> items [BRCMF_PCIE_FW_NVRAM ].nv_data .data ;
22922427 nvram_len = fwreq -> items [BRCMF_PCIE_FW_NVRAM ].nv_data .len ;
22932428 devinfo -> clm_fw = fwreq -> items [BRCMF_PCIE_FW_CLM ].binary ;
@@ -2298,6 +2433,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
22982433 if (ret ) {
22992434 brcmf_err (bus , "Failed to get RAM info\n" );
23002435 release_firmware (fw );
2436+ release_firmware (fwsig );
23012437 brcmf_fw_nvram_free (nvram );
23022438 goto fail ;
23032439 }
@@ -2309,7 +2445,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
23092445 */
23102446 brcmf_pcie_adjust_ramsize (devinfo , (u8 * )fw -> data , fw -> size );
23112447
2312- ret = brcmf_pcie_download_fw_nvram (devinfo , fw , nvram , nvram_len );
2448+ ret = brcmf_pcie_download_fw_nvram (devinfo , fw , fwsig , nvram , nvram_len );
23132449 if (ret )
23142450 goto fail ;
23152451
@@ -2374,6 +2510,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
23742510 { ".txt" , devinfo -> nvram_name },
23752511 { ".clm_blob" , devinfo -> clm_name },
23762512 { ".txcap_blob" , devinfo -> txcap_name },
2513+ { ".sig" , devinfo -> sig_name },
23772514 };
23782515
23792516 fwreq = brcmf_fw_alloc_request (devinfo -> ci -> chip , devinfo -> ci -> chiprev ,
@@ -2384,6 +2521,8 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
23842521 return NULL ;
23852522
23862523 fwreq -> items [BRCMF_PCIE_FW_CODE ].type = BRCMF_FW_TYPE_BINARY ;
2524+ fwreq -> items [BRCMF_PCIE_FW_SIG ].type = BRCMF_FW_TYPE_BINARY ;
2525+ fwreq -> items [BRCMF_PCIE_FW_SIG ].flags = BRCMF_FW_REQF_OPTIONAL ;
23872526 fwreq -> items [BRCMF_PCIE_FW_NVRAM ].type = BRCMF_FW_TYPE_NVRAM ;
23882527 fwreq -> items [BRCMF_PCIE_FW_NVRAM ].flags = BRCMF_FW_REQF_OPTIONAL ;
23892528 fwreq -> items [BRCMF_PCIE_FW_CLM ].type = BRCMF_FW_TYPE_BINARY ;
0 commit comments