@@ -82,6 +82,7 @@ FILE *logfile_f = NULL;
82
82
static Hashmap * items = NULL ;
83
83
static Hashmap * items_failed = NULL ;
84
84
static Hashmap * modules_loaded = NULL ;
85
+ static Hashmap * modules_suppliers = NULL ;
85
86
static regex_t mod_filter_path ;
86
87
static regex_t mod_filter_nopath ;
87
88
static regex_t mod_filter_symbol ;
@@ -94,7 +95,7 @@ static bool arg_mod_filter_nosymbol = false;
94
95
static bool arg_mod_filter_noname = false;
95
96
96
97
static int dracut_install (const char * src , const char * dst , bool isdir , bool resolvedeps , bool hashdst );
97
- static int install_dependent_modules (struct kmod_list * modlist );
98
+ static int install_dependent_modules (struct kmod_ctx * ctx , struct kmod_list * modlist , Hashmap * suppliers_paths );
98
99
99
100
static void item_free (char * i )
100
101
{
@@ -1499,7 +1500,111 @@ static bool check_module_path(const char *path)
1499
1500
return true;
1500
1501
}
1501
1502
1502
- static int install_dependent_module (struct kmod_module * mod , int * err )
1503
+ static int find_kmod_module_from_sysfs_node (struct kmod_ctx * ctx , const char * sysfs_node , int sysfs_node_len ,
1504
+ struct kmod_list * * modules )
1505
+ {
1506
+ char modalias_path [PATH_MAX ];
1507
+ if (snprintf (modalias_path , sizeof (modalias_path ), "%.*s/modalias" , sysfs_node_len ,
1508
+ sysfs_node ) >= sizeof (modalias_path ))
1509
+ return -1 ;
1510
+
1511
+ _cleanup_close_ int modalias_file = -1 ;
1512
+ if ((modalias_file = open (modalias_path , O_RDONLY | O_CLOEXEC )) == -1 )
1513
+ return 0 ;
1514
+
1515
+ char alias [page_size ()];
1516
+ ssize_t len = read (modalias_file , alias , sizeof (alias ));
1517
+ alias [len - 1 ] = '\0' ;
1518
+
1519
+ return kmod_module_new_from_lookup (ctx , alias , modules );
1520
+ }
1521
+
1522
+ static int find_modules_from_sysfs_node (struct kmod_ctx * ctx , const char * sysfs_node , Hashmap * modules )
1523
+ {
1524
+ _cleanup_kmod_module_unref_list_ struct kmod_list * list = NULL ;
1525
+ struct kmod_list * l = NULL ;
1526
+
1527
+ if (find_kmod_module_from_sysfs_node (ctx , sysfs_node , strlen (sysfs_node ), & list ) >= 0 ) {
1528
+ kmod_list_foreach (l , list ) {
1529
+ struct kmod_module * mod = kmod_module_get_module (l );
1530
+ char * module = strdup (kmod_module_get_name (mod ));
1531
+ kmod_module_unref (mod );
1532
+
1533
+ if (hashmap_put (modules , module , module ) < 0 )
1534
+ free (module );
1535
+ }
1536
+ }
1537
+
1538
+ return 0 ;
1539
+ }
1540
+
1541
+ static void find_suppliers_for_sys_node (struct kmod_ctx * ctx , Hashmap * suppliers , const char * node_path_raw ,
1542
+ size_t node_path_len )
1543
+ {
1544
+ char node_path [PATH_MAX ];
1545
+ char real_path [PATH_MAX ];
1546
+
1547
+ memcpy (node_path , node_path_raw , node_path_len );
1548
+ node_path [node_path_len ] = '\0' ;
1549
+
1550
+ DIR * d ;
1551
+ struct dirent * dir ;
1552
+ while (realpath (node_path , real_path ) != NULL && strcmp (real_path , "/sys/devices" )) {
1553
+ d = opendir (node_path );
1554
+ if (d ) {
1555
+ size_t real_path_len = strlen (real_path );
1556
+ while ((dir = readdir (d )) != NULL ) {
1557
+ if (strstr (dir -> d_name , "supplier:platform" ) != NULL ) {
1558
+ if (snprintf (real_path + real_path_len , sizeof (real_path ) - real_path_len , "/%s/supplier" ,
1559
+ dir -> d_name ) < sizeof (real_path ) - real_path_len ) {
1560
+ char * real_supplier_path = realpath (real_path , NULL );
1561
+ if (real_supplier_path != NULL )
1562
+ if (hashmap_put (suppliers , real_supplier_path , real_supplier_path ) < 0 )
1563
+ free (real_supplier_path );
1564
+ }
1565
+ }
1566
+ }
1567
+ closedir (d );
1568
+ }
1569
+ strncat (node_path , "/.." , 3 ); // Also find suppliers of parents
1570
+ }
1571
+ }
1572
+
1573
+ static void find_suppliers (struct kmod_ctx * ctx )
1574
+ {
1575
+ _cleanup_fts_close_ FTS * fts ;
1576
+ char * paths [] = { "/sys/devices/platform" , NULL };
1577
+ fts = fts_open (paths , FTS_NOSTAT | FTS_PHYSICAL , NULL );
1578
+
1579
+ for (FTSENT * ftsent = fts_read (fts ); ftsent != NULL ; ftsent = fts_read (fts )) {
1580
+ if (strcmp (ftsent -> fts_name , "modalias" ) == 0 ) {
1581
+ _cleanup_kmod_module_unref_list_ struct kmod_list * list = NULL ;
1582
+ struct kmod_list * l ;
1583
+
1584
+ if (find_kmod_module_from_sysfs_node (ctx , ftsent -> fts_parent -> fts_path , ftsent -> fts_parent -> fts_pathlen , & list ) < 0 )
1585
+ continue ;
1586
+
1587
+ kmod_list_foreach (l , list ) {
1588
+ _cleanup_kmod_module_unref_ struct kmod_module * mod = kmod_module_get_module (l );
1589
+ const char * name = kmod_module_get_name (mod );
1590
+ Hashmap * suppliers = hashmap_get (modules_suppliers , name );
1591
+ if (suppliers == NULL ) {
1592
+ suppliers = hashmap_new (string_hash_func , string_compare_func );
1593
+ hashmap_put (modules_suppliers , strdup (name ), suppliers );
1594
+ }
1595
+
1596
+ find_suppliers_for_sys_node (ctx , suppliers , ftsent -> fts_parent -> fts_path , ftsent -> fts_parent -> fts_pathlen );
1597
+ }
1598
+ }
1599
+ }
1600
+ }
1601
+
1602
+ static Hashmap * find_suppliers_paths_for_module (const char * module )
1603
+ {
1604
+ return hashmap_get (modules_suppliers , module );
1605
+ }
1606
+
1607
+ static int install_dependent_module (struct kmod_ctx * ctx , struct kmod_module * mod , Hashmap * suppliers_paths , int * err )
1503
1608
{
1504
1609
const char * path = NULL ;
1505
1610
const char * name = NULL ;
@@ -1530,13 +1635,13 @@ static int install_dependent_module(struct kmod_module *mod, int *err)
1530
1635
log_debug ("dracut_install '%s' '%s' OK" , path , & path [kerneldirlen ]);
1531
1636
install_firmware (mod );
1532
1637
modlist = kmod_module_get_dependencies (mod );
1533
- * err = install_dependent_modules (modlist );
1638
+ * err = install_dependent_modules (ctx , modlist , suppliers_paths );
1534
1639
if (* err == 0 ) {
1535
1640
* err = kmod_module_get_softdeps (mod , & modpre , & modpost );
1536
1641
if (* err == 0 ) {
1537
1642
int r ;
1538
- * err = install_dependent_modules (modpre );
1539
- r = install_dependent_modules (modpost );
1643
+ * err = install_dependent_modules (ctx , modpre , NULL );
1644
+ r = install_dependent_modules (ctx , modpost , NULL );
1540
1645
* err = * err ? : r ;
1541
1646
}
1542
1647
}
@@ -1547,22 +1652,46 @@ static int install_dependent_module(struct kmod_module *mod, int *err)
1547
1652
return 0 ;
1548
1653
}
1549
1654
1550
- static int install_dependent_modules (struct kmod_list * modlist )
1655
+ static int install_dependent_modules (struct kmod_ctx * ctx , struct kmod_list * modlist , Hashmap * suppliers_paths )
1551
1656
{
1552
1657
struct kmod_list * itr = NULL ;
1553
1658
int ret = 0 ;
1554
1659
1555
1660
kmod_list_foreach (itr , modlist ) {
1556
1661
_cleanup_kmod_module_unref_ struct kmod_module * mod = NULL ;
1557
1662
mod = kmod_module_get_module (itr );
1558
- if (install_dependent_module (mod , & ret ))
1663
+ if (install_dependent_module (ctx , mod , find_suppliers_paths_for_module ( kmod_module_get_name ( mod )) , & ret ))
1559
1664
return -1 ;
1560
1665
}
1561
1666
1667
+ const char * supplier_path ;
1668
+ Iterator i ;
1669
+ HASHMAP_FOREACH (supplier_path , suppliers_paths , i ) {
1670
+ _cleanup_destroy_hashmap_ Hashmap * modules = hashmap_new (string_hash_func , string_compare_func );
1671
+ find_modules_from_sysfs_node (ctx , supplier_path , modules );
1672
+
1673
+ _cleanup_destroy_hashmap_ Hashmap * suppliers = hashmap_new (string_hash_func , string_compare_func );
1674
+ find_suppliers_for_sys_node (ctx , suppliers , supplier_path , strlen (supplier_path ));
1675
+
1676
+ if (!hashmap_isempty (modules )) { // Supplier is a module
1677
+ const char * module ;
1678
+ Iterator j ;
1679
+ HASHMAP_FOREACH (module , modules , j ) {
1680
+ _cleanup_kmod_module_unref_ struct kmod_module * mod = NULL ;
1681
+ if (!kmod_module_new_from_name (ctx , module , & mod )) {
1682
+ if (install_dependent_module (ctx , mod , suppliers , & ret ))
1683
+ return -1 ;
1684
+ }
1685
+ }
1686
+ } else { // Supplier is builtin
1687
+ install_dependent_modules (ctx , NULL , suppliers );
1688
+ }
1689
+ }
1690
+
1562
1691
return ret ;
1563
1692
}
1564
1693
1565
- static int install_module (struct kmod_module * mod )
1694
+ static int install_module (struct kmod_ctx * ctx , struct kmod_module * mod )
1566
1695
{
1567
1696
int ret = 0 ;
1568
1697
_cleanup_kmod_module_unref_list_ struct kmod_list * modlist = NULL ;
@@ -1612,15 +1741,16 @@ static int install_module(struct kmod_module *mod)
1612
1741
}
1613
1742
install_firmware (mod );
1614
1743
1744
+ Hashmap * suppliers = find_suppliers_paths_for_module (name );
1615
1745
modlist = kmod_module_get_dependencies (mod );
1616
- ret = install_dependent_modules (modlist );
1746
+ ret = install_dependent_modules (ctx , modlist , suppliers );
1617
1747
1618
1748
if (ret == 0 ) {
1619
1749
ret = kmod_module_get_softdeps (mod , & modpre , & modpost );
1620
1750
if (ret == 0 ) {
1621
1751
int r ;
1622
- ret = install_dependent_modules (modpre );
1623
- r = install_dependent_modules (modpost );
1752
+ ret = install_dependent_modules (ctx , modpre , NULL );
1753
+ r = install_dependent_modules (ctx , modpost , NULL );
1624
1754
ret = ret ? : r ;
1625
1755
}
1626
1756
}
@@ -1731,6 +1861,9 @@ static int install_modules(int argc, char **argv)
1731
1861
if (p != NULL )
1732
1862
kerneldirlen = p - abskpath ;
1733
1863
1864
+ modules_suppliers = hashmap_new (string_hash_func , string_compare_func );
1865
+ find_suppliers (ctx );
1866
+
1734
1867
if (arg_hostonly ) {
1735
1868
char * modalias_file ;
1736
1869
modalias_file = getenv ("DRACUT_KERNEL_MODALIASES" );
@@ -1818,7 +1951,7 @@ static int install_modules(int argc, char **argv)
1818
1951
}
1819
1952
kmod_list_foreach (itr , modlist ) {
1820
1953
mod = kmod_module_get_module (itr );
1821
- r = install_module (mod );
1954
+ r = install_module (ctx , mod );
1822
1955
kmod_module_unref (mod );
1823
1956
if ((r < 0 ) && !arg_optional ) {
1824
1957
if (!arg_silent )
@@ -1897,7 +2030,7 @@ static int install_modules(int argc, char **argv)
1897
2030
}
1898
2031
kmod_list_foreach (itr , modlist ) {
1899
2032
mod = kmod_module_get_module (itr );
1900
- r = install_module (mod );
2033
+ r = install_module (ctx , mod );
1901
2034
kmod_module_unref (mod );
1902
2035
if ((r < 0 ) && !arg_optional ) {
1903
2036
if (!arg_silent )
@@ -1948,7 +2081,7 @@ static int install_modules(int argc, char **argv)
1948
2081
}
1949
2082
kmod_list_foreach (itr , modlist ) {
1950
2083
mod = kmod_module_get_module (itr );
1951
- r = install_module (mod );
2084
+ r = install_module (ctx , mod );
1952
2085
kmod_module_unref (mod );
1953
2086
if ((r < 0 ) && !arg_optional ) {
1954
2087
if (!arg_silent )
@@ -2111,9 +2244,18 @@ int main(int argc, char **argv)
2111
2244
while ((i = hashmap_steal_first (items_failed )))
2112
2245
item_free (i );
2113
2246
2247
+ Hashmap * h ;
2248
+ while ((h = hashmap_steal_first (modules_suppliers ))) {
2249
+ while ((i = hashmap_steal_first (h ))) {
2250
+ item_free (i );
2251
+ }
2252
+ hashmap_free (h );
2253
+ }
2254
+
2114
2255
hashmap_free (items );
2115
2256
hashmap_free (items_failed );
2116
2257
hashmap_free (modules_loaded );
2258
+ hashmap_free (modules_suppliers );
2117
2259
2118
2260
strv_free (firmwaredirs );
2119
2261
strv_free (pathdirs );
0 commit comments